diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 4ab689719..2a51f008d 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -2054,6 +2054,16 @@ "invalidSeedPhraseCaseSensitive": { "message": "Invalid input! Secret Recovery Phrase is case sensitive." }, + "ipfsToggleModalDescriptionOne": { + "message": "We use third-party services to show images of your NFTs stored on IPFS, display information related to ENS addresses entered in your browser's address bar, and fetch icons for different tokens. Your IP address may be exposed to these services when you’re using them." + }, + "ipfsToggleModalDescriptionTwo": { + "message": "Selecting Confirm turns on IPFS resolution. You can turn it off in $1 at any time.", + "description": "$1 is the method to turn off ipfs" + }, + "ipfsToggleModalSettings": { + "message": "Settings > Security and privacy" + }, "jazzAndBlockies": { "message": "Jazzicons and Blockies are two different styles of unique icons that help you identify an account at a glance." }, @@ -3821,6 +3831,9 @@ "showMore": { "message": "Show more" }, + "showNft": { + "message": "Show NFT" + }, "showPermissions": { "message": "Show permissions" }, diff --git a/app/images/default_nft.png b/app/images/default_nft.png new file mode 100644 index 000000000..a398aeba5 Binary files /dev/null and b/app/images/default_nft.png differ diff --git a/test/e2e/nft/erc721-interaction.spec.js b/test/e2e/nft/erc721-interaction.spec.js index d88f31f64..e979a8530 100644 --- a/test/e2e/nft/erc721-interaction.spec.js +++ b/test/e2e/nft/erc721-interaction.spec.js @@ -93,7 +93,7 @@ describe('ERC721 NFTs testdapp interaction', function () { await driver.clickElement({ text: 'NFTs', tag: 'button' }); await driver.findElement({ text: 'TestDappNFTs (3)' }); const nftsListItemsFirstCheck = await driver.findElements( - '.nft-item__item', + '.nft-item__container', ); assert.equal(nftsListItemsFirstCheck.length, 3); @@ -119,7 +119,7 @@ describe('ERC721 NFTs testdapp interaction', function () { await driver.clickElement({ text: 'NFTs', tag: 'button' }); await driver.findElement({ text: 'TestDappNFTs (6)' }); const nftsListItemsSecondCheck = await driver.findElements( - '.nft-item__item', + '.nft-item__container', ); assert.equal(nftsListItemsSecondCheck.length, 6); }, @@ -215,7 +215,7 @@ describe('ERC721 NFTs testdapp interaction', function () { await driver.clickElement({ text: 'NFTs', tag: 'button' }); await driver.findElement({ text: 'TestDappNFTs (5)' }); const nftsListItemsSecondCheck = await driver.findElements( - '.nft-item__item', + '.nft-item__container', ); assert.equal(nftsListItemsSecondCheck.length, 5); diff --git a/test/e2e/nft/import-erc1155.spec.js b/test/e2e/nft/import-erc1155.spec.js index 516b82aba..b3640f8c4 100644 --- a/test/e2e/nft/import-erc1155.spec.js +++ b/test/e2e/nft/import-erc1155.spec.js @@ -58,7 +58,7 @@ describe('Import ERC1155 NFT', function () { assert.equal(await importedERC1155.isDisplayed(), true); const importedERC1155Image = await driver.findVisibleElement( - '.nft-item__item', + '.nft-item__container', ); assert.equal(await importedERC1155Image.isDisplayed(), true); }, diff --git a/test/e2e/nft/import-nft.spec.js b/test/e2e/nft/import-nft.spec.js index c0fc22876..e98c9dbb9 100644 --- a/test/e2e/nft/import-nft.spec.js +++ b/test/e2e/nft/import-nft.spec.js @@ -56,7 +56,7 @@ describe('Import NFT', function () { text: 'TestDappNFTs', }); const importedNftImage = await driver.findElement( - '.nft-item__item-image', + '.nft-item__container', ); assert.equal(await importedNft.isDisplayed(), true); assert.equal(await importedNftImage.isDisplayed(), true); diff --git a/test/e2e/nft/remove-erc1155.spec.js b/test/e2e/nft/remove-erc1155.spec.js index 90f0be7db..377d7a592 100644 --- a/test/e2e/nft/remove-erc1155.spec.js +++ b/test/e2e/nft/remove-erc1155.spec.js @@ -32,7 +32,7 @@ describe('Remove ERC1155 NFT', function () { // Open the details page and click remove nft button await driver.clickElement('[data-testid="home__nfts-tab"]'); const importedNftImage = await driver.findVisibleElement( - '.nft-item__item', + '.nft-item__container', ); await importedNftImage.click(); await driver.clickElement('[data-testid="nft-options__button"]'); diff --git a/test/e2e/nft/remove-nft.spec.js b/test/e2e/nft/remove-nft.spec.js index 6edf681ef..d491f488f 100644 --- a/test/e2e/nft/remove-nft.spec.js +++ b/test/e2e/nft/remove-nft.spec.js @@ -31,7 +31,7 @@ describe('Remove NFT', function () { // Open the details and click remove nft button await driver.clickElement('[data-testid="home__nfts-tab"]'); - await driver.clickElement('.nft-item__item-image'); + await driver.clickElement('.nft-item__container'); await driver.clickElement('[data-testid="nft-options__button"]'); await driver.clickElement('[data-testid="nft-item-remove"]'); diff --git a/test/e2e/nft/send-nft.spec.js b/test/e2e/nft/send-nft.spec.js index 9e801ec70..63ff670d3 100644 --- a/test/e2e/nft/send-nft.spec.js +++ b/test/e2e/nft/send-nft.spec.js @@ -31,7 +31,7 @@ describe('Send NFT', function () { // Fill the send NFT form and confirm the transaction await driver.clickElement('[data-testid="home__nfts-tab"]'); - await driver.clickElement('.nft-item__item-image'); + await driver.clickElement('.nft-item__container'); await driver.clickElement({ text: 'Send', tag: 'button' }); await driver.fill( 'input[placeholder="Enter public address (0x) or ENS name"]', diff --git a/test/e2e/nft/view-erc1155-details.spec.js b/test/e2e/nft/view-erc1155-details.spec.js index 65bf128b8..3d811b8bb 100644 --- a/test/e2e/nft/view-erc1155-details.spec.js +++ b/test/e2e/nft/view-erc1155-details.spec.js @@ -34,7 +34,7 @@ describe('View ERC1155 NFT details', function () { // Click to open the NFT details page and check displayed account await driver.clickElement('[data-testid="home__nfts-tab"]'); const importedNftImage = await driver.findVisibleElement( - '.nft-item__item', + '.nft-item__container', ); await importedNftImage.click(); const detailsPageAccount = await driver.findElement( @@ -54,7 +54,7 @@ describe('View ERC1155 NFT details', function () { 'This is a collection of Rock NFTs.', ); - const nftImage = await driver.findElement('.nft-item__item-image'); + const nftImage = await driver.findElement('.nft-item__container'); assert.equal(await nftImage.isDisplayed(), true); const nftImageSource = await driver.findElement( diff --git a/test/e2e/nft/view-nft-details.spec.js b/test/e2e/nft/view-nft-details.spec.js index 2c3169dbe..07251050a 100644 --- a/test/e2e/nft/view-nft-details.spec.js +++ b/test/e2e/nft/view-nft-details.spec.js @@ -33,7 +33,7 @@ describe('View NFT details', function () { // Click to open the NFT details page and check title await driver.clickElement('[data-testid="home__nfts-tab"]'); - await driver.clickElement('.nft-item__item-image'); + await driver.clickElement('.nft-item__container'); const detailsPageTitle = await driver.findElement('.asset-breadcrumb'); assert.equal( @@ -53,7 +53,7 @@ describe('View NFT details', function () { 'Test Dapp NFTs for testing.', ); - const nftImage = await driver.findElement('.nft-item__item-image'); + const nftImage = await driver.findElement('.nft-item__container'); assert.equal(await nftImage.isDisplayed(), true); const nftImageSource = await driver.findElement( diff --git a/ui/components/app/nft-default-image/__snapshots__/nft-default-image.test.js.snap b/ui/components/app/nft-default-image/__snapshots__/nft-default-image.test.js.snap index 7fd606daa..ad5821e56 100644 --- a/ui/components/app/nft-default-image/__snapshots__/nft-default-image.test.js.snap +++ b/ui/components/app/nft-default-image/__snapshots__/nft-default-image.test.js.snap @@ -3,58 +3,29 @@ exports[`NFT Default Image should match snapshot with all provided props 1`] = `
-
- NFT Name - -
- # - 123 -
-
+ />
`; exports[`NFT Default Image should match snapshot with missing clickable prop 1`] = `
-
- NFT Name - -
- # - 123 -
-
+ />
`; exports[`NFT Default Image should render with no props 1`] = `
-
- [unknownCollection] - -
- # -
-
+ />
`; diff --git a/ui/components/app/nft-default-image/index.scss b/ui/components/app/nft-default-image/index.scss index e76dbec41..a75286299 100644 --- a/ui/components/app/nft-default-image/index.scss +++ b/ui/components/app/nft-default-image/index.scss @@ -1,17 +1,12 @@ .nft-default { padding-top: 100%; position: relative; + background-image: url('/images/default_nft.png'); + background-size: cover; + background-repeat: no-repeat; - &--clickable { - cursor: pointer; - } - - &__text { - overflow: hidden; + &__button { position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - width: calc(100% - 32px); + bottom: 16px; } } diff --git a/ui/components/app/nft-default-image/nft-default-image.js b/ui/components/app/nft-default-image/nft-default-image.js index 54c5d688d..9d70df63f 100644 --- a/ui/components/app/nft-default-image/nft-default-image.js +++ b/ui/components/app/nft-default-image/nft-default-image.js @@ -1,27 +1,23 @@ import React from 'react'; import PropTypes from 'prop-types'; import classnames from 'classnames'; +import { useDispatch, useSelector } from 'react-redux'; import { Display, AlignItems, - BlockSize, JustifyContent, - TextVariant, BorderRadius, - TextAlign, - BackgroundColor, } from '../../../helpers/constants/design-system'; import { useI18nContext } from '../../../hooks/useI18nContext'; -import { Text } from '../../component-library'; -import Box from '../../ui/box/box'; +import { ButtonLink, Box } from '../../component-library'; +import { showIpfsModal } from '../../../store/actions'; +import { getIpfsGateway } from '../../../selectors'; -export default function NftDefaultImage({ - name, - tokenId, - className, - clickable = false, -}) { +export default function NftDefaultImage({ className, clickable }) { const t = useI18nContext(); + const dispatch = useDispatch(); + const isIpfsEnabled = useSelector(getIpfsGateway); + return ( - - {name ?? t('unknownCollection')}
#{tokenId} -
+ {!isIpfsEnabled && ( + { + e.stopPropagation(); + dispatch(showIpfsModal()); + }} + > + {t('show')} + + )}
); } NftDefaultImage.propTypes = { - /** - * The name of the NFT collection if not supplied will default to "Unnamed collection" - */ - name: PropTypes.string, - /** - * The token id of the nft - */ - tokenId: PropTypes.string, /** * Controls the css class for the cursor hover */ diff --git a/ui/components/app/nft-default-image/nft-default-image.stories.js b/ui/components/app/nft-default-image/nft-default-image.stories.js index 3f83fcf95..02959ebef 100644 --- a/ui/components/app/nft-default-image/nft-default-image.stories.js +++ b/ui/components/app/nft-default-image/nft-default-image.stories.js @@ -5,21 +5,10 @@ export default { title: 'Components/App/NftDefaultImage', argTypes: { - name: { - control: 'text', - }, - tokenId: { - control: 'text', - }, clickable: { control: 'boolean', }, }, - args: { - name: null, - tokenId: '12345', - clickable: true, - }, }; export const DefaultStory = (args) => ( diff --git a/ui/components/app/nft-default-image/nft-default-image.test.js b/ui/components/app/nft-default-image/nft-default-image.test.js index 3077f68de..f66044bdf 100644 --- a/ui/components/app/nft-default-image/nft-default-image.test.js +++ b/ui/components/app/nft-default-image/nft-default-image.test.js @@ -1,72 +1,54 @@ import React from 'react'; +import configureStore from 'redux-mock-store'; import { renderWithProvider } from '../../../../test/lib/render-helpers'; +import mockState from '../../../../test/data/mock-state.json'; import NftDefaultImage from '.'; describe('NFT Default Image', () => { + const mockShowIpfsModal = jest.fn(); + jest.mock('../../../store/actions.ts', () => ({ + showIpfsModal: () => mockShowIpfsModal, + })); + + const store = configureStore()(mockState); + it('should render with no props', () => { - const { container } = renderWithProvider(); + const { container } = renderWithProvider(, store); expect(container).toMatchSnapshot(); }); it('should match snapshot with all provided props', () => { const props = { - name: 'NFT Name', - tokenId: '123', - clickable: true, + clickable: false, }; - const { container } = renderWithProvider(); + const { container } = renderWithProvider( + , + store, + ); expect(container).toMatchSnapshot(); }); it('should match snapshot with missing clickable prop', () => { - const props = { - name: 'NFT Name', - tokenId: '123', - }; - - const { container } = renderWithProvider(); + const { container } = renderWithProvider(, store); expect(container).toMatchSnapshot(); }); - it('should render NFT name', () => { - const props = { - name: 'NFT Name', - }; - - const { queryByText } = renderWithProvider(); - - const nftElement = queryByText(`${props.name} #`); - - expect(nftElement).toBeInTheDocument(); - }); - - it('should render NFT name and tokenId', () => { - const props = { - name: 'NFT Name', - tokenId: '123', - }; - - const { queryByText } = renderWithProvider(); - - const nftElement = queryByText(`${props.name} #${props.tokenId}`); - - expect(nftElement).toBeInTheDocument(); - }); - it('does not render component with clickable class when clickable is false', () => { const { container } = renderWithProvider( - , + , + store, ); expect(container.firstChild).not.toHaveClass('nft-default--clickable'); }); it('renders component with clickable class when clickable is true', () => { const { container } = renderWithProvider( - , + , + store, ); expect(container.firstChild).toHaveClass('nft-default--clickable'); }); diff --git a/ui/components/app/nft-default-image/toggle-ipfs-modal.js b/ui/components/app/nft-default-image/toggle-ipfs-modal.js new file mode 100644 index 000000000..1dc120771 --- /dev/null +++ b/ui/components/app/nft-default-image/toggle-ipfs-modal.js @@ -0,0 +1,70 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { useDispatch } from 'react-redux'; +import { + Box, + ButtonPrimary, + Modal, + ModalContent, + ModalHeader, + ModalOverlay, + Text, +} from '../../component-library'; +import { useI18nContext } from '../../../hooks/useI18nContext'; +import { hideIpfsModal, setIpfsGateway } from '../../../store/actions'; +import { IPFS_DEFAULT_GATEWAY_URL } from '../../../../shared/constants/network'; +import { + Size, + TextColor, + TextVariant, +} from '../../../helpers/constants/design-system'; + +export const ToggleIpfsModal = ({ onClose }) => { + const t = useI18nContext(); + const dispatch = useDispatch(); + + return ( + + + + {t('showNft')} + + + {t('ipfsToggleModalDescriptionOne')} + + + {t('ipfsToggleModalDescriptionTwo', [ + + {t('ipfsToggleModalSettings')}, + , + ])} + + + { + dispatch(setIpfsGateway(IPFS_DEFAULT_GATEWAY_URL)); + dispatch(hideIpfsModal()); + }} + size={Size.LG} + > + {t('confirm')} + + + + ); +}; + +ToggleIpfsModal.propTypes = { + onClose: PropTypes.func.isRequired, +}; diff --git a/ui/components/app/nft-details/__snapshots__/nft-details.test.js.snap b/ui/components/app/nft-details/__snapshots__/nft-details.test.js.snap index 6ce126fef..643500500 100644 --- a/ui/components/app/nft-details/__snapshots__/nft-details.test.js.snap +++ b/ui/components/app/nft-details/__snapshots__/nft-details.test.js.snap @@ -56,7 +56,7 @@ exports[`NFT Details should match minimal props and state snapshot 1`] = ` alt="MUNK #1 1" class="mm-box nft-item__item nft-item__item-image mm-box--display-block mm-box--justify-content-center" data-testid="nft-image" - src="https://bafybeiclzx7zfjvuiuwobn5ip3ogc236bjqfjzoblumf4pau4ep6dqramu.ipfs.dweb.link" + src="ipfs://QmTSZUNt8AKyDabkyXXXP4oHWDnaVXgNdXoJGEyaYzLbeL" />

diff --git a/ui/components/app/nfts-items/nfts-items.js b/ui/components/app/nfts-items/nfts-items.js index 35e498274..ff044f4c2 100644 --- a/ui/components/app/nfts-items/nfts-items.js +++ b/ui/components/app/nfts-items/nfts-items.js @@ -52,6 +52,7 @@ export default function NftsItems({ const chainId = useSelector(getCurrentChainId); const currentChain = useSelector(getCurrentNetwork); const t = useI18nContext(); + const ipfsGateway = useSelector(getIpfsGateway); useEffect(() => { if ( @@ -86,7 +87,6 @@ export default function NftsItems({ dispatch, ]); - const ipfsGateway = useSelector(getIpfsGateway); const history = useHistory(); const renderCollectionImage = (collectionImage, collectionName) => { @@ -169,9 +169,13 @@ export default function NftsItems({ {isExpanded ? ( {nfts.map((nft, i) => { - const { image, address, tokenId, name } = nft; - const nftImage = getAssetImageURL(image, ipfsGateway); + const { image, address, tokenId, name, imageOriginal } = nft; + const nftImage = getAssetImageURL(imageOriginal, ipfsGateway); const nftImageAlt = getNftImageAlt(nft); + const nftImageURL = imageOriginal?.includes('ipfs') + ? nftImage + : image; + const handleImageClick = () => history.push(`${ASSET_ROUTE}/${address}/${tokenId}`); return ( @@ -182,8 +186,9 @@ export default function NftsItems({ className="nfts-items__item-wrapper" > { ); const nftImages = queryAllByTestId('nft-image'); - - fireEvent.click(nftImages[0]); + const nftDefaultImages = queryAllByTestId('nft-default-image'); + if (nftImages.length) { + fireEvent.click(nftImages[0]); + } else { + fireEvent.click(nftDefaultImages[0]); + } const firstNft = nfts[0]; const nftRoute = `/asset/${firstNft.address}/${firstNft.tokenId}`; diff --git a/ui/components/multichain/nft-item/nft-item.js b/ui/components/multichain/nft-item/nft-item.js index a4f60bf01..a0fc767ef 100644 --- a/ui/components/multichain/nft-item/nft-item.js +++ b/ui/components/multichain/nft-item/nft-item.js @@ -15,7 +15,10 @@ import { Display, JustifyContent, } from '../../../helpers/constants/design-system'; -import { getTestNetworkBackgroundColor } from '../../../selectors'; +import { + getIpfsGateway, + getTestNetworkBackgroundColor, +} from '../../../selectors'; export const NftItem = ({ alt, @@ -25,9 +28,12 @@ export const NftItem = ({ networkSrc, tokenId, onClick, - clickable = false, + clickable, + nftImageURL, }) => { const testNetworkBackgroundColor = useSelector(getTestNetworkBackgroundColor); + const isIpfsEnabled = useSelector(getIpfsGateway); + const isIpfsURL = nftImageURL?.includes('ipfs:'); return ( } > - {src ? ( + {isIpfsEnabled ? ( ) : ( - + <> + {isIpfsURL ? ( + + ) : ( + + )} + )} @@ -91,4 +111,5 @@ NftItem.propTypes = { tokenId: PropTypes.string.isRequired, onClick: PropTypes.func, clickable: PropTypes.bool, + nftImageURL: PropTypes.string, }; diff --git a/ui/components/multichain/nft-item/nft-item.test.js b/ui/components/multichain/nft-item/nft-item.test.js index e9b0179b4..45559e177 100644 --- a/ui/components/multichain/nft-item/nft-item.test.js +++ b/ui/components/multichain/nft-item/nft-item.test.js @@ -1,13 +1,28 @@ import React from 'react'; -import configureStore from 'redux-mock-store'; import { fireEvent } from '@testing-library/react'; +import configureStore from '../../../store/store'; import '@testing-library/jest-dom/extend-expect'; import mockState from '../../../../test/data/mock-state.json'; import { renderWithProvider } from '../../../../test/lib/render-helpers'; import { NftItem } from '.'; +const store = configureStore({ + metamask: { + ...mockState.metamask, + }, +}); + +const noIpfsStore = configureStore({ + metamask: { + ...mockState.metamask, + ipfsGateway: '', + }, +}); + describe('NftItem component', () => { - const store = configureStore()(mockState); + jest.mock('../../../store/actions.ts', () => ({ + getTokenStandardAndDetails: jest.fn().mockResolvedValue(), + })); describe('render', () => { const props = { alt: 'Test Alt', @@ -18,6 +33,7 @@ describe('NftItem component', () => { networkSrc: 'test-network-src', tokenId: '1', onClick: jest.fn(), + nftImageURL: '', }; it('renders correctly with an image source', () => { @@ -29,10 +45,13 @@ describe('NftItem component', () => { expect(getByTestId('nft-image')).toHaveAttribute('src', 'test-src'); }); - it('renders correctly with default image when no image source is provided', () => { + it('renders correctly with default image when no ipfs is off and no image is provided', () => { const { getByTestId, queryByTestId } = renderWithProvider( - , - store, + , + noIpfsStore, ); expect(queryByTestId('nft-image')).not.toBeInTheDocument(); diff --git a/ui/ducks/app/app.ts b/ui/ducks/app/app.ts index e2b3a151e..e34edcf2d 100644 --- a/ui/ducks/app/app.ts +++ b/ui/ducks/app/app.ts @@ -27,6 +27,7 @@ interface AppState { } | null; networkDropdownOpen: boolean; importNftsModalOpen: boolean; + showIpfsModalOpen: boolean; accountDetail: { subview?: string; accountExport?: string; @@ -96,6 +97,7 @@ const initialState: AppState = { qrCodeData: null, networkDropdownOpen: false, importNftsModalOpen: false, + showIpfsModalOpen: false, accountDetail: { privateKey: '', }, @@ -176,6 +178,19 @@ export default function reduceApp( ...appState, importNftsModalOpen: false, }; + + case actionConstants.SHOW_IPFS_MODAL_OPEN: + return { + ...appState, + showIpfsModalOpen: true, + }; + + case actionConstants.SHOW_IPFS_MODAL_CLOSE: + return { + ...appState, + showIpfsModalOpen: false, + }; + // alert methods case actionConstants.ALERT_OPEN: return { diff --git a/ui/pages/routes/routes.component.js b/ui/pages/routes/routes.component.js index 59b9bf73f..d6280a79c 100644 --- a/ui/pages/routes/routes.component.js +++ b/ui/pages/routes/routes.component.js @@ -117,6 +117,7 @@ import DeprecatedTestNetworks from '../../components/ui/deprecated-test-networks import NewNetworkInfo from '../../components/ui/new-network-info/new-network-info'; import { ThemeType } from '../../../shared/constants/preferences'; import { Box } from '../../components/component-library'; +import { ToggleIpfsModal } from '../../components/app/nft-default-image/toggle-ipfs-modal'; export default class Routes extends Component { static propTypes = { @@ -159,6 +160,8 @@ export default class Routes extends Component { accountDetailsAddress: PropTypes.string, isImportNftsModalOpen: PropTypes.bool.isRequired, hideImportNftsModal: PropTypes.func.isRequired, + isIpfsModalOpen: PropTypes.bool.isRequired, + hideIpfsModal: PropTypes.func.isRequired, }; static contextTypes = { @@ -515,6 +518,8 @@ export default class Routes extends Component { location, isImportNftsModalOpen, hideImportNftsModal, + isIpfsModalOpen, + hideIpfsModal, } = this.props; const loadMessage = loadingMessage || isNetworkLoading @@ -576,6 +581,9 @@ export default class Routes extends Component { {isImportNftsModalOpen ? ( hideImportNftsModal()} /> ) : null} + {isIpfsModalOpen ? ( + hideIpfsModal()} /> + ) : null} {isLoading ? : null} {!isLoading && isNetworkLoading ? : null} diff --git a/ui/pages/routes/routes.container.js b/ui/pages/routes/routes.container.js index 5f31829d1..03c0e7f46 100644 --- a/ui/pages/routes/routes.container.js +++ b/ui/pages/routes/routes.container.js @@ -16,6 +16,7 @@ import { import { lockMetamask, hideImportNftsModal, + hideIpfsModal, setCurrentCurrency, setLastActiveTime, setMouseUserState, @@ -65,6 +66,7 @@ function mapStateToProps(state) { isNetworkMenuOpen: state.metamask.isNetworkMenuOpen, accountDetailsAddress: state.appState.accountDetailsAddress, isImportNftsModalOpen: state.appState.importNftsModalOpen, + isIpfsModalOpen: state.appState.showIpfsModalOpen, }; } @@ -80,6 +82,7 @@ function mapDispatchToProps(dispatch) { toggleAccountMenu: () => dispatch(toggleAccountMenu()), toggleNetworkMenu: () => dispatch(toggleNetworkMenu()), hideImportNftsModal: () => dispatch(hideImportNftsModal()), + hideIpfsModal: () => dispatch(hideIpfsModal()), }; } diff --git a/ui/pages/settings/security-tab/__snapshots__/security-tab.test.js.snap b/ui/pages/settings/security-tab/__snapshots__/security-tab.test.js.snap index f6d77b174..23cf0907a 100644 --- a/ui/pages/settings/security-tab/__snapshots__/security-tab.test.js.snap +++ b/ui/pages/settings/security-tab/__snapshots__/security-tab.test.js.snap @@ -381,6 +381,55 @@ exports[`Security Tab should match snapshot 1`] = ` The IPFS gateway makes it possible to access and view data hosted by third parties. You can add a custom IPFS gateway or continue using the default.

+
+