From 663942d1ac2698dc289699852cb11d6c9b780f9b Mon Sep 17 00:00:00 2001 From: Nicholas Gambino Date: Fri, 17 Jan 2025 17:21:16 -0800 Subject: [PATCH] chore: Convert monolithic component into smaller pieces --- app/components/UI/NftGrid/NftGrid.tsx | 134 +------------------- app/components/UI/NftGrid/NftGridEmpty.tsx | 76 +++++++++++ app/components/UI/NftGrid/NftGridFooter.tsx | 47 +++++++ app/components/UI/NftGrid/NftGridItem.tsx | 118 +---------------- 4 files changed, 134 insertions(+), 241 deletions(-) diff --git a/app/components/UI/NftGrid/NftGrid.tsx b/app/components/UI/NftGrid/NftGrid.tsx index 9d85658d96c..0e43b3a033c 100644 --- a/app/components/UI/NftGrid/NftGrid.tsx +++ b/app/components/UI/NftGrid/NftGrid.tsx @@ -1,16 +1,12 @@ import React, { useCallback, useRef, useState } from 'react'; import { View, - TouchableOpacity, Alert, - ScrollView, ActivityIndicator, - Image, FlatList, RefreshControl, } from 'react-native'; import { useSelector } from 'react-redux'; -import CollectibleMedia from '../CollectibleMedia'; import ActionSheet from '@metamask/react-native-actionsheet'; import { strings } from '../../../../locales/i18n'; import Engine from '../../../core/Engine'; @@ -20,36 +16,24 @@ import { isNftFetchingProgressSelector, } from '../../../reducers/collectibles'; import { useTheme } from '../../../util/theme'; -import Text, { - TextColor, - TextVariant, -} from '../../../component-library/components/Texts/Text'; import { MetaMetricsEvents, useMetrics, } from '../../../components/hooks/useMetrics'; import { getDecimalChainId } from '../../../util/networks'; import { Nft } from '@metamask/assets-controllers'; -import { debounce } from 'lodash'; import styleSheet from './NftGrid.styles'; import { useStyles } from '../../hooks/useStyles'; import { StackNavigationProp } from '@react-navigation/stack'; -import { WalletViewSelectorsIDs } from '../../../../e2e/selectors/wallet/WalletView.selectors'; import CollectibleDetectionModal from '../CollectibleDetectionModal'; import { selectUseNftDetection } from '../../../selectors/preferencesController'; -import ButtonLink from '../../../component-library/components/Buttons/Button/variants/ButtonLink'; -import AppConstants from '../../../core/AppConstants'; import { RefreshTestId, SpinnerTestId, } from '../CollectibleContracts/constants'; import NftGridItem from './NftGridItem'; - -const noNftPlaceholderSrc = require('../../../images/no-nfts-placeholder.png'); - -const debouncedNavigation = debounce((navigation, collectible) => { - navigation.navigate('NftDetails', { collectible }); -}, 200); +import NftGridEmpty from './NftGridEmpty'; +import NftGridFooter from './NftGridFooter'; interface ActionSheetType { show: () => void; @@ -98,11 +82,6 @@ function NftGrid({ navigation, chainId, selectedAddress }: NftGridProps) { }); }, [setRefreshing]); - const onLongPressCollectible = useCallback((collectible) => { - actionSheetRef?.current?.show(); - longPressedCollectible.current = collectible; - }, []); - const removeNft = () => { const { NftController } = Engine.context; @@ -160,107 +139,6 @@ function NftGrid({ navigation, chainId, selectedAddress }: NftGridProps) { } }; - const onItemPress = useCallback( - (collectible) => { - debouncedNavigation(navigation, collectible); - }, - [navigation], - ); - - const renderCollectible = (collectible: Nft, index: number) => { - if (!collectible) return null; - return ( - onItemPress(collectible)} - onLongPress={() => onLongPressCollectible(collectible)} - testID={collectible.name as string} - > - - - {collectible.name} - - - {collectible.collection?.name} - - - ); - }; - - const NftGridFooter = () => ( - - - {strings('wallet.no_collectibles')} - - - navigation.push('AddAsset', { assetType: 'collectible' }) - } - disabled={false} - testID={WalletViewSelectorsIDs.IMPORT_NFT_BUTTON} - > - - {strings('wallet.add_collectibles')} - - - - ); - - const NftGridEmpty = () => ( - - - - {strings('wallet.no_nfts_yet')} - - - navigation.navigate('Webview', { - screen: 'SimpleWebview', - params: { url: AppConstants.URLS.NFT }, - }) - } - testID={WalletViewSelectorsIDs.IMPORT_NFT_BUTTON} - > - console.log('goToLearnMore')} - > - {strings('wallet.learn_more')} - - - - ); - return ( {!isNftDetectionEnabled && } @@ -275,8 +153,8 @@ function NftGrid({ navigation, chainId, selectedAddress }: NftGridProps) { {/* empty state */} {!isNftFetchingProgress && collectibles.length === 0 && ( <> - - + + )} {/* nft grid */} @@ -284,7 +162,7 @@ function NftGrid({ navigation, chainId, selectedAddress }: NftGridProps) { ( + renderItem={({ item }: { item: Nft }) => ( )} keyExtractor={(_, index) => index.toString()} @@ -297,7 +175,7 @@ function NftGrid({ navigation, chainId, selectedAddress }: NftGridProps) { onRefresh={onRefresh} /> } - ListFooterComponent={} + ListFooterComponent={} /> )} ; +} + +function NftGridEmpty({ navigation }: NftGridProps) { + const { styles } = useStyles(styleSheet, {}); + + return ( + + + + {strings('wallet.no_nfts_yet')} + + + navigation.navigate('Webview', { + screen: 'SimpleWebview', + params: { url: AppConstants.URLS.NFT }, + }) + } + testID={WalletViewSelectorsIDs.IMPORT_NFT_BUTTON} + > + console.log('goToLearnMore')} + > + {strings('wallet.learn_more')} + + + + ); +} + +export default NftGridEmpty; diff --git a/app/components/UI/NftGrid/NftGridFooter.tsx b/app/components/UI/NftGrid/NftGridFooter.tsx index e69de29bb2d..7e126a47de8 100644 --- a/app/components/UI/NftGrid/NftGridFooter.tsx +++ b/app/components/UI/NftGrid/NftGridFooter.tsx @@ -0,0 +1,47 @@ +import React from 'react'; +import { View, TouchableOpacity } from 'react-native'; +import { strings } from '../../../../locales/i18n'; +import Text, { + TextColor, + TextVariant, +} from '../../../component-library/components/Texts/Text'; // TextVariant, // TextColor, +import { StackNavigationProp } from '@react-navigation/stack'; +import { WalletViewSelectorsIDs } from '../../../../e2e/selectors/wallet/WalletView.selectors'; + +interface NftGridNavigationParamList { + AddAsset: { assetType: string }; + [key: string]: undefined | object; +} + +interface NftGridFooterProps { + navigation: StackNavigationProp; +} + +function NftGridFooter({ navigation }: NftGridFooterProps) { + return ( + + + {strings('wallet.no_collectibles')} + + + navigation.push('AddAsset', { assetType: 'collectible' }) + } + disabled={false} + testID={WalletViewSelectorsIDs.IMPORT_NFT_BUTTON} + > + + {strings('wallet.add_collectibles')} + + + + ); +} + +export default NftGridFooter; diff --git a/app/components/UI/NftGrid/NftGridItem.tsx b/app/components/UI/NftGrid/NftGridItem.tsx index 7e78d19d494..c1c55859e0d 100644 --- a/app/components/UI/NftGrid/NftGridItem.tsx +++ b/app/components/UI/NftGrid/NftGridItem.tsx @@ -1,50 +1,12 @@ -import React, { useCallback, useRef, useState } from 'react'; -import { - View, - TouchableOpacity, - Alert, - ScrollView, - ActivityIndicator, - Image, - FlatList, - RefreshControl, -} from 'react-native'; -import { useSelector } from 'react-redux'; +import React, { useCallback, useRef } from 'react'; +import { TouchableOpacity } from 'react-native'; import CollectibleMedia from '../CollectibleMedia'; -import ActionSheet from '@metamask/react-native-actionsheet'; -import { strings } from '../../../../locales/i18n'; -import Engine from '../../../core/Engine'; -import { removeFavoriteCollectible } from '../../../actions/collectibles'; -import { - collectiblesSelector, - isNftFetchingProgressSelector, -} from '../../../reducers/collectibles'; -import { useTheme } from '../../../util/theme'; -import Text, { - TextColor, - TextVariant, -} from '../../../component-library/components/Texts/Text'; -import { - MetaMetricsEvents, - useMetrics, -} from '../../../components/hooks/useMetrics'; -import { getDecimalChainId } from '../../../util/networks'; +import Text from '../../../component-library/components/Texts/Text'; import { Nft } from '@metamask/assets-controllers'; import { debounce } from 'lodash'; import styleSheet from './NftGrid.styles'; import { useStyles } from '../../hooks/useStyles'; import { StackNavigationProp } from '@react-navigation/stack'; -import { WalletViewSelectorsIDs } from '../../../../e2e/selectors/wallet/WalletView.selectors'; -import CollectibleDetectionModal from '../CollectibleDetectionModal'; -import { selectUseNftDetection } from '../../../selectors/preferencesController'; -import ButtonLink from '../../../component-library/components/Buttons/Button/variants/ButtonLink'; -import AppConstants from '../../../core/AppConstants'; -import { - RefreshTestId, - SpinnerTestId, -} from '../CollectibleContracts/constants'; - -const noNftPlaceholderSrc = require('../../../images/no-nfts-placeholder.png'); const debouncedNavigation = debounce((navigation, collectible) => { navigation.navigate('NftDetails', { collectible }); @@ -76,83 +38,12 @@ function NftGridItem({ null, ); const { styles } = useStyles(styleSheet, {}); - const { trackEvent, createEventBuilder } = useMetrics(); - - const onRefresh = useCallback(async () => { - requestAnimationFrame(async () => { - setRefreshing(true); - const { NftDetectionController, NftController } = Engine.context; - const actions = [ - NftDetectionController.detectNfts(), - NftController.checkAndUpdateAllNftsOwnershipStatus(), - ]; - await Promise.allSettled(actions); - setRefreshing(false); - }); - }, [setRefreshing]); const onLongPressCollectible = useCallback((collectible) => { actionSheetRef?.current?.show(); longPressedCollectible.current = collectible; }, []); - const removeNft = () => { - const { NftController } = Engine.context; - - if ( - !longPressedCollectible?.current?.address && - !longPressedCollectible?.current?.tokenId - ) { - return null; - } - - removeFavoriteCollectible( - selectedAddress, - chainId, - longPressedCollectible.current, - ); - NftController.removeAndIgnoreNft( - longPressedCollectible.current.address, - longPressedCollectible.current.tokenId, - ); - - trackEvent( - createEventBuilder(MetaMetricsEvents.COLLECTIBLE_REMOVED) - .addProperties({ - chain_id: getDecimalChainId(chainId), - }) - .build(), - ); - Alert.alert( - strings('wallet.collectible_removed_title'), - strings('wallet.collectible_removed_desc'), - ); - }; - - const refreshMetadata = () => { - const { NftController } = Engine.context; - - if ( - !longPressedCollectible?.current?.address && - !longPressedCollectible?.current?.tokenId - ) { - return null; - } - - NftController.addNft( - longPressedCollectible.current.address, - longPressedCollectible.current.tokenId, - ); - }; - - const handleMenuAction = (index: number) => { - if (index === 1) { - removeNft(); - } else if (index === 0) { - refreshMetadata(); - } - }; - const onItemPress = useCallback( (nftItem) => { debouncedNavigation(navigation, nftItem); @@ -161,6 +52,7 @@ function NftGridItem({ ); if (!nft) return null; + return (