diff --git a/app/components/UI/AssetOverview/TokenDetails/TokenDetails.tsx b/app/components/UI/AssetOverview/TokenDetails/TokenDetails.tsx index 8864c78c35c..476ab653953 100644 --- a/app/components/UI/AssetOverview/TokenDetails/TokenDetails.tsx +++ b/app/components/UI/AssetOverview/TokenDetails/TokenDetails.tsx @@ -5,7 +5,7 @@ import { useSelector } from 'react-redux'; import i18n from '../../../../../locales/i18n'; import { useStyles } from '../../../../component-library/hooks'; import styleSheet from './TokenDetails.styles'; -import { formatAddress, safeToChecksumAddress } from '../../../../util/address'; +import { safeToChecksumAddress } from '../../../../util/address'; import { selectTokenList } from '../../../../selectors/tokenListController'; import { selectContractExchangeRates } from '../../../../selectors/tokenRatesController'; import { @@ -75,13 +75,12 @@ const TokenDetails: React.FC = ({ asset }) => { const tokenDetails: TokenDetails = asset.isETH ? { - contractAddress: formatAddress(zeroAddress(), 'short'), + contractAddress: zeroAddress(), tokenDecimal: 18, tokenList: '', } : { - contractAddress: - formatAddress(tokenContractAddress as string, 'short') || null, + contractAddress: tokenContractAddress || null, tokenDecimal: tokenMetadata?.decimals || null, tokenList: tokenMetadata?.aggregators.join(', ') || null, }; diff --git a/app/components/UI/AssetOverview/TokenDetails/TokenDetailsList/TokenDetailsList.tsx b/app/components/UI/AssetOverview/TokenDetails/TokenDetailsList/TokenDetailsList.tsx index b218361c5ff..7697440bfbd 100644 --- a/app/components/UI/AssetOverview/TokenDetails/TokenDetailsList/TokenDetailsList.tsx +++ b/app/components/UI/AssetOverview/TokenDetails/TokenDetailsList/TokenDetailsList.tsx @@ -17,6 +17,7 @@ import Icon, { import ClipboardManager from '../../../../../core/ClipboardManager'; import { TokenDetails } from '../TokenDetails'; import TokenDetailsListItem from '../TokenDetailsListItem'; +import { formatAddress } from '../../../../../util/address'; interface TokenDetailsListProps { tokenDetails: TokenDetails; @@ -62,7 +63,7 @@ const TokenDetailsList: React.FC = ({ onPress={copyAccountToClipboard} > - {tokenDetails.contractAddress} + {formatAddress(tokenDetails.contractAddress, 'short')} account.address); + +const MOCK_ACCOUNT_1: Account = { + name: 'Account 1', + address: toChecksumAddress(MOCK_ACCOUNT_ADDRESSES[0]) as Hex, + type: KeyringTypes.hd, + yOffset: 0, + isSelected: false, + assets: { + fiatBalance: '\n0 ETH', + }, + balanceError: undefined, +}; +const MOCK_ACCOUNT_2: Account = { + name: 'Account 2', + address: toChecksumAddress(MOCK_ACCOUNT_ADDRESSES[1]) as Hex, + type: KeyringTypes.hd, + yOffset: 78, + isSelected: true, + assets: { + fiatBalance: '\n< 0.00001 ETH', + }, + balanceError: undefined, +}; + +const MOCK_ACCOUNTS = [MOCK_ACCOUNT_1, MOCK_ACCOUNT_2]; + +const mockInitialState: DeepPartial = { + engine: { + backgroundState: { + ...backgroundState, + NotificationServicesController: { + metamaskNotificationsList: [], + }, + }, + }, +}; + +describe('AccountsList', () => { + it('matches snapshot', () => { + + const { toJSON } = renderWithProvider( + , + { + state: mockInitialState, + }, + ); + expect(toJSON()).toMatchSnapshot(); + }); + + it('triggers updateAndfetchAccountSettings on mount', () => { + const updateAndfetchAccountSettings = jest.fn(); + renderWithProvider( + , + { + state: mockInitialState, + }, + ); + + expect(updateAndfetchAccountSettings).toHaveBeenCalledTimes(1); + }); +}); diff --git a/app/components/Views/Settings/NotificationsSettings/AccountsList.tsx b/app/components/Views/Settings/NotificationsSettings/AccountsList.tsx new file mode 100644 index 00000000000..8dded276cf9 --- /dev/null +++ b/app/components/Views/Settings/NotificationsSettings/AccountsList.tsx @@ -0,0 +1,53 @@ +import React, { useEffect } from 'react'; +import { FlatList, View } from 'react-native'; +import NotificationOptionToggle from './NotificationOptionToggle'; +import { Account } from '../../../../components/hooks/useAccounts/useAccounts.types'; +import { NotificationsToggleTypes } from './NotificationsSettings.constants'; +import { NotificationsAccountsState } from '../../../../core/redux/slices/notifications'; +import { AvatarAccountType } from '../../../../component-library/components/Avatars/Avatar'; + +export const AccountsList = ({ + accounts, + accountAvatarType, + accountSettingsData, + updateAndfetchAccountSettings, + isUpdatingMetamaskNotificationsAccount, +}: { + accounts: Account[]; + accountAvatarType: AvatarAccountType; + accountSettingsData: NotificationsAccountsState; + updateAndfetchAccountSettings: () => Promise | undefined>; + isUpdatingMetamaskNotificationsAccount: string[]; +}) => { + + useEffect(() => { + const fetchInitialData = async () => { + await updateAndfetchAccountSettings(); + }; + fetchInitialData(); + }, [updateAndfetchAccountSettings]); + + return ( + + `address-${item.address}`} + renderItem={({ item }) => ( + 0} + isLoading={isUpdatingMetamaskNotificationsAccount.includes( + item.address.toLowerCase(), + )} + isEnabled={accountSettingsData?.[item.address.toLowerCase()]} + updateAndfetchAccountSettings={updateAndfetchAccountSettings} + /> + )} + /> + + ); +}; diff --git a/app/components/Views/Settings/NotificationsSettings/NotificationOptionToggle/index.tsx b/app/components/Views/Settings/NotificationsSettings/NotificationOptionToggle/index.tsx index d04cad3c248..ad6ae7921a3 100644 --- a/app/components/Views/Settings/NotificationsSettings/NotificationOptionToggle/index.tsx +++ b/app/components/Views/Settings/NotificationsSettings/NotificationOptionToggle/index.tsx @@ -34,7 +34,7 @@ interface NotificationOptionsToggleProps { disabledSwitch?: boolean; isLoading?: boolean; isEnabled: boolean; - refetchAccountSettings: () => Promise; + updateAndfetchAccountSettings: () => Promise | undefined>; } /** @@ -50,7 +50,7 @@ const NotificationOptionToggle = ({ isEnabled, disabledSwitch, isLoading, - refetchAccountSettings, + updateAndfetchAccountSettings, }: NotificationOptionsToggleProps) => { const theme = useTheme(); const { colors } = theme; @@ -59,7 +59,7 @@ const NotificationOptionToggle = ({ const { toggleAccount, loading: isUpdatingAccount } = useUpdateAccountSetting( address, - refetchAccountSettings, + updateAndfetchAccountSettings, ); const loading = isLoading || isUpdatingAccount; @@ -104,7 +104,7 @@ const NotificationOptionToggle = ({ )} - {isLoading || loading ? ( + {loading ? ( ) : ( }, button: { alignSelf: 'stretch', - marginBottom: 16, + marginBottom: 48, + }, + + }); + + export const styles = StyleSheet.create({ + headerLeft: { + marginHorizontal: 16, }, }); diff --git a/app/components/Views/Settings/NotificationsSettings/__snapshots__/AccountsList.test.tsx.snap b/app/components/Views/Settings/NotificationsSettings/__snapshots__/AccountsList.test.tsx.snap new file mode 100644 index 00000000000..621e0158390 --- /dev/null +++ b/app/components/Views/Settings/NotificationsSettings/__snapshots__/AccountsList.test.tsx.snap @@ -0,0 +1,520 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`AccountsList matches snapshot 1`] = ` + + + + + + + + + + + + + + + + + + + Account 1 + + + 0xc495...d272 + + + + + + + + + + + + + + + + + + + + + + + Account 2 + + + 0xc496...a756 + + + + + + + + + + +`; diff --git a/app/components/Views/Settings/NotificationsSettings/index.tsx b/app/components/Views/Settings/NotificationsSettings/index.tsx index e046b203c2e..20456dc6389 100644 --- a/app/components/Views/Settings/NotificationsSettings/index.tsx +++ b/app/components/Views/Settings/NotificationsSettings/index.tsx @@ -1,6 +1,5 @@ -/* eslint-disable react-native/no-inline-styles */ /* eslint-disable react/display-name */ -import React, { useEffect, useMemo, useCallback } from 'react'; +import React, { useEffect, useCallback } from 'react'; import { ScrollView, Switch, View, Linking } from 'react-native'; import { useSelector } from 'react-redux'; import { NavigationProp, ParamListBase } from '@react-navigation/native'; @@ -13,6 +12,7 @@ import Text, { TextVariant, TextColor, } from '../../../../component-library/components/Texts/Text'; +import { AccountsList} from './AccountsList'; import { useAccounts } from '../../../../components/hooks/useAccounts'; import { useMetrics } from '../../../../components/hooks/useMetrics'; import { AvatarAccountType } from '../../../../component-library/components/Avatars/Avatar'; @@ -21,9 +21,7 @@ import SwitchLoadingModal from '../../../UI/Notification/SwitchLoadingModal'; import { Props } from './NotificationsSettings.types'; import { useStyles } from '../../../../component-library/hooks'; -import NotificationOptionToggle from './NotificationOptionToggle'; import CustomNotificationsRow from './CustomNotificationsRow'; -import { NotificationsToggleTypes } from './NotificationsSettings.constants'; import { selectIsFeatureAnnouncementsEnabled, selectIsMetamaskNotificationsEnabled, @@ -51,7 +49,7 @@ import { useAccountSettingsProps, useSwitchNotifications, } from '../../../../util/notifications/hooks/useSwitchNotifications'; -import styleSheet from './NotificationsSettings.styles'; +import styleSheet, { styles as navigationOptionsStyles } from './NotificationsSettings.styles'; import AppConstants from '../../../../core/AppConstants'; import notificationsRows from './notificationsRows'; import { IconName } from '../../../../component-library/components/Icons/Icon'; @@ -121,19 +119,6 @@ const NotificationsSettings = ({ navigation, route }: Props) => { selectIsUpdatingMetamaskNotificationsAccount, ); - const accountAddresses = useMemo( - () => accounts.map((a) => a.address), - [accounts], - ); - - const { switchFeatureAnnouncements } = useSwitchNotifications(); - - // Account Settings - const accountSettingsProps = useAccountSettingsProps(accountAddresses); - const refetchAccountSettings = useCallback(async () => { - await accountSettingsProps.update(accountAddresses); - }, [accountAddresses, accountSettingsProps]); - const { enableNotifications, loading: enableLoading, @@ -146,6 +131,9 @@ const NotificationsSettings = ({ navigation, route }: Props) => { error: disablingError, } = useDisableNotifications(); + const { switchFeatureAnnouncements } = useSwitchNotifications(); + const { updateAndfetchAccountSettings } = useAccountSettingsProps(accounts); + const accountAvatarType = useSelector((state: RootState) => state.settings.useBlockieIcon ? AvatarAccountType.Blockies @@ -157,7 +145,7 @@ const NotificationsSettings = ({ navigation, route }: Props) => { const [uiNotificationStatus, setUiNotificationStatus] = React.useState(false); const [platformAnnouncementsState, setPlatformAnnouncementsState] = React.useState(isFeatureAnnouncementsEnabled); - + const accountSettingsData = useSelector((state: RootState) => state.notifications); const loading = enableLoading || disableLoading; const errorText = enablingError || disablingError; const loadingText = !uiNotificationStatus @@ -170,7 +158,7 @@ const NotificationsSettings = ({ navigation, route }: Props) => { const isFullScreenModal = route?.params?.isFullScreenModal; // Style const { colors } = theme; - const { styles } = useStyles(styleSheet, {}); + const { styles } = useStyles(styleSheet, { theme }); /** * Initializes the notifications feature. @@ -220,37 +208,6 @@ const NotificationsSettings = ({ navigation, route }: Props) => { ); }, [colors, isFullScreenModal, navigation]); - const renderAccounts = useCallback( - () => - accounts.map((account) => { - const isEnabled = - accountSettingsProps.data?.[account.address.toLowerCase()]; - return ( - 0} - isLoading={accountSettingsProps.accountsBeingUpdated.includes( - account.address.toLowerCase(), - )} - isEnabled={isEnabled ?? false} - refetchAccountSettings={refetchAccountSettings} - /> - ); - }), - // eslint-disable-next-line react-hooks/exhaustive-deps - [ - accountSettingsProps.data, - accountSettingsProps.accountsBeingUpdated, - accountAvatarType, - isUpdatingMetamaskNotificationsAccount.length, - refetchAccountSettings, - ], - ); - const renderResetNotificationsBtn = useCallback(() => (