This reverts commit 81ea24f08a
.
feature/default_network_editable
parent
79867bcebe
commit
9e2935dd55
@ -1,61 +0,0 @@ |
||||
import { cloneDeep } from 'lodash'; |
||||
import { IPFS_DEFAULT_GATEWAY_URL } from '../../../shared/constants/network'; |
||||
|
||||
const version = 68; |
||||
|
||||
function addUrlProtocolPrefix(urlString) { |
||||
if (!urlString.match(/(^http:\/\/)|(^https:\/\/)/u)) { |
||||
return `https://${urlString}`; |
||||
} |
||||
return urlString; |
||||
} |
||||
|
||||
export default { |
||||
version, |
||||
|
||||
async migrate(originalVersionedData) { |
||||
const versionedData = cloneDeep(originalVersionedData); |
||||
versionedData.meta.version = version; |
||||
const state = versionedData.data; |
||||
const newState = transformState(state); |
||||
versionedData.data = newState; |
||||
return versionedData; |
||||
}, |
||||
}; |
||||
|
||||
function transformState(state) { |
||||
const PreferencesController = state?.PreferencesController || {}; |
||||
const preferences = PreferencesController.preferences || {}; |
||||
const oldIpfsGateWay = preferences.ipfsGateway; |
||||
|
||||
let newState; |
||||
|
||||
if (oldIpfsGateWay && oldIpfsGateWay !== 'dweb.link') { |
||||
const newIpfsGateway = new URL( |
||||
addUrlProtocolPrefix(oldIpfsGateWay), |
||||
).toString(); |
||||
newState = { |
||||
...state, |
||||
PreferencesController: { |
||||
...PreferencesController, |
||||
preferences: { |
||||
...preferences, |
||||
ipfsGateway: newIpfsGateway, |
||||
}, |
||||
}, |
||||
}; |
||||
} else { |
||||
newState = { |
||||
...state, |
||||
PreferencesController: { |
||||
...PreferencesController, |
||||
preferences: { |
||||
...preferences, |
||||
ipfsGateway: IPFS_DEFAULT_GATEWAY_URL, |
||||
}, |
||||
}, |
||||
}; |
||||
} |
||||
|
||||
return newState; |
||||
} |
@ -1,56 +0,0 @@ |
||||
import { IPFS_DEFAULT_GATEWAY_URL } from '../../../shared/constants/network'; |
||||
import migration68 from './068'; |
||||
|
||||
describe('migration #68', () => { |
||||
it('should update the version metadata', async () => { |
||||
const oldStorage = { |
||||
meta: { |
||||
version: 67, |
||||
}, |
||||
data: {}, |
||||
}; |
||||
|
||||
const newStorage = await migration68.migrate(oldStorage); |
||||
expect(newStorage.meta).toStrictEqual({ |
||||
version: 68, |
||||
}); |
||||
}); |
||||
|
||||
it('should set preference ipfsGateway to "https://cloudflare-ipfs.com" if ipfsGateway is old default dweb.link', async () => { |
||||
const expectedValue = IPFS_DEFAULT_GATEWAY_URL; // = https://cloudflare-ipfs.com
|
||||
const oldStorage = { |
||||
meta: {}, |
||||
data: { |
||||
PreferencesController: { |
||||
preferences: { |
||||
ipfsGateway: 'dweb.link', |
||||
}, |
||||
}, |
||||
}, |
||||
}; |
||||
|
||||
const newStorage = await migration68.migrate(oldStorage); |
||||
expect(newStorage.data.PreferencesController.preferences.ipfsGateway).toBe( |
||||
expectedValue, |
||||
); |
||||
}); |
||||
|
||||
it('should update preference ipfsGateway to a full url version of user set ipfsGateway if ipfsGateway is not old default dweb.link', async () => { |
||||
const expectedValue = 'https://random.ipfs/'; |
||||
const oldStorage = { |
||||
meta: {}, |
||||
data: { |
||||
PreferencesController: { |
||||
preferences: { |
||||
ipfsGateway: 'random.ipfs', |
||||
}, |
||||
}, |
||||
}, |
||||
}; |
||||
|
||||
const newStorage = await migration68.migrate(oldStorage); |
||||
expect(newStorage.data.PreferencesController.preferences.ipfsGateway).toBe( |
||||
expectedValue, |
||||
); |
||||
}); |
||||
}); |
@ -1,212 +0,0 @@ |
||||
import React from 'react'; |
||||
import PropTypes from 'prop-types'; |
||||
import { useDispatch, useSelector } from 'react-redux'; |
||||
import { useHistory } from 'react-router-dom'; |
||||
import { getTokenTrackerLink } from '@metamask/etherscan-link'; |
||||
import Box from '../../ui/box'; |
||||
import Typography from '../../ui/typography/typography'; |
||||
import { |
||||
COLORS, |
||||
TYPOGRAPHY, |
||||
BLOCK_SIZES, |
||||
FONT_WEIGHT, |
||||
JUSTIFY_CONTENT, |
||||
FLEX_DIRECTION, |
||||
OVERFLOW_WRAP, |
||||
DISPLAY, |
||||
} from '../../../helpers/constants/design-system'; |
||||
import { useI18nContext } from '../../../hooks/useI18nContext'; |
||||
import { |
||||
getAssetImageURL, |
||||
isEqualCaseInsensitive, |
||||
shortenAddress, |
||||
} from '../../../helpers/utils/util'; |
||||
import { |
||||
getCurrentChainId, |
||||
getIpfsGateway, |
||||
getRpcPrefsForCurrentProvider, |
||||
getSelectedIdentity, |
||||
} from '../../../selectors'; |
||||
import AssetNavigation from '../../../pages/asset/components/asset-navigation'; |
||||
import { getCollectibleContracts } from '../../../ducks/metamask/metamask'; |
||||
import { DEFAULT_ROUTE } from '../../../helpers/constants/routes'; |
||||
import { removeAndIgnoreCollectible } from '../../../store/actions'; |
||||
import { |
||||
GOERLI_CHAIN_ID, |
||||
KOVAN_CHAIN_ID, |
||||
MAINNET_CHAIN_ID, |
||||
POLYGON_CHAIN_ID, |
||||
RINKEBY_CHAIN_ID, |
||||
ROPSTEN_CHAIN_ID, |
||||
} from '../../../../shared/constants/network'; |
||||
import { getEnvironmentType } from '../../../../app/scripts/lib/util'; |
||||
import { ENVIRONMENT_TYPE_POPUP } from '../../../../shared/constants/app'; |
||||
import CollectibleOptions from './collectible-options'; |
||||
|
||||
export default function CollectibleDetails({ collectible }) { |
||||
const { image, name, description, address, tokenId } = collectible; |
||||
const t = useI18nContext(); |
||||
const history = useHistory(); |
||||
const rpcPrefs = useSelector(getRpcPrefsForCurrentProvider); |
||||
const ipfsGateway = useSelector(getIpfsGateway); |
||||
const collectibleContracts = useSelector(getCollectibleContracts); |
||||
const currentNetwork = useSelector(getCurrentChainId); |
||||
|
||||
const collectibleContractName = collectibleContracts.find( |
||||
({ address: contractAddress }) => |
||||
isEqualCaseInsensitive(contractAddress, address), |
||||
)?.name; |
||||
const selectedAccountName = useSelector( |
||||
(state) => getSelectedIdentity(state).name, |
||||
); |
||||
const collectibleImageURL = getAssetImageURL(image, ipfsGateway); |
||||
const dispatch = useDispatch(); |
||||
|
||||
const onRemove = () => { |
||||
dispatch(removeAndIgnoreCollectible(address, tokenId)); |
||||
history.push(DEFAULT_ROUTE); |
||||
}; |
||||
|
||||
const getOpenSeaLink = () => { |
||||
switch (currentNetwork) { |
||||
case MAINNET_CHAIN_ID: |
||||
return `https://opensea.io/assets/${address}/${tokenId}`; |
||||
case POLYGON_CHAIN_ID: |
||||
return `https://opensea.io/assets/matic/${address}/${tokenId}`; |
||||
case GOERLI_CHAIN_ID: |
||||
case KOVAN_CHAIN_ID: |
||||
case ROPSTEN_CHAIN_ID: |
||||
case RINKEBY_CHAIN_ID: |
||||
return `https://testnets.opensea.io/assets/${address}/${tokenId}`; |
||||
default: |
||||
return null; |
||||
} |
||||
}; |
||||
|
||||
const openSeaLink = getOpenSeaLink(); |
||||
return ( |
||||
<> |
||||
<AssetNavigation |
||||
accountName={selectedAccountName} |
||||
assetName={collectibleContractName} |
||||
onBack={() => history.push(DEFAULT_ROUTE)} |
||||
optionsButton={ |
||||
<CollectibleOptions |
||||
onViewOnOpensea={ |
||||
openSeaLink |
||||
? () => global.platform.openTab({ url: openSeaLink }) |
||||
: null |
||||
} |
||||
onRemove={onRemove} |
||||
/> |
||||
} |
||||
/> |
||||
<Box padding={[4, 2, 4, 2]}> |
||||
<div className="collectible-details"> |
||||
<Box margin={3} padding={2} justifyContent={JUSTIFY_CONTENT.CENTER}> |
||||
<img style={{ width: '14rem' }} src={collectibleImageURL} /> |
||||
</Box> |
||||
<Box |
||||
margin={3} |
||||
flexDirection={FLEX_DIRECTION.COLUMN} |
||||
width={ |
||||
getEnvironmentType() === ENVIRONMENT_TYPE_POPUP |
||||
? BLOCK_SIZES.THREE_FOURTHS |
||||
: BLOCK_SIZES.HALF |
||||
} |
||||
> |
||||
<Typography |
||||
color={COLORS.BLACK} |
||||
variant={TYPOGRAPHY.H4} |
||||
fontWeight={FONT_WEIGHT.BOLD} |
||||
> |
||||
{name} |
||||
</Typography> |
||||
<Typography |
||||
color={COLORS.UI3} |
||||
variant={TYPOGRAPHY.H5} |
||||
boxProps={{ marginTop: 2, marginBottom: 3 }} |
||||
overflowWrap={OVERFLOW_WRAP.BREAK_WORD} |
||||
> |
||||
{`#${tokenId}`} |
||||
</Typography> |
||||
<Typography |
||||
color={COLORS.BLACK} |
||||
variant={TYPOGRAPHY.H6} |
||||
fontWeight={FONT_WEIGHT.BOLD} |
||||
className="collectible-details__description" |
||||
> |
||||
{t('description')} |
||||
</Typography> |
||||
<Typography color={COLORS.UI3} variant={TYPOGRAPHY.H6}> |
||||
{description} |
||||
</Typography> |
||||
</Box> |
||||
</div> |
||||
<Box margin={4}> |
||||
<Box display={DISPLAY.FLEX} flexDirection={FLEX_DIRECTION.ROW}> |
||||
<Typography |
||||
color={COLORS.BLACK} |
||||
variant={TYPOGRAPHY.H6} |
||||
fontWeight={FONT_WEIGHT.BOLD} |
||||
boxProps={{ marginBottom: 3, width: BLOCK_SIZES.ONE_FOURTH }} |
||||
> |
||||
{t('source')} |
||||
</Typography> |
||||
<Typography |
||||
color={COLORS.PRIMARY1} |
||||
variant={TYPOGRAPHY.H6} |
||||
boxProps={{ marginBottom: 3, width: BLOCK_SIZES.THREE_FOURTHS }} |
||||
overflowWrap={OVERFLOW_WRAP.BREAK_WORD} |
||||
> |
||||
<a |
||||
target="_blank" |
||||
href={collectibleImageURL} |
||||
rel="noopener noreferrer" |
||||
style={{ overflow: 'hidden', textOverflow: 'ellipsis' }} |
||||
> |
||||
{image} |
||||
</a> |
||||
</Typography> |
||||
</Box> |
||||
<Box display={DISPLAY.FLEX} flexDirection={FLEX_DIRECTION.ROW}> |
||||
<Typography |
||||
color={COLORS.BLACK} |
||||
variant={TYPOGRAPHY.H6} |
||||
fontWeight={FONT_WEIGHT.BOLD} |
||||
boxProps={{ width: BLOCK_SIZES.ONE_FOURTH }} |
||||
> |
||||
{t('contractAddress')} |
||||
</Typography> |
||||
<Typography |
||||
color={COLORS.UI3} |
||||
variant={TYPOGRAPHY.H6} |
||||
overflowWrap={OVERFLOW_WRAP.BREAK_WORD} |
||||
boxProps={{ width: BLOCK_SIZES.THREE_FOURTHS }} |
||||
> |
||||
<a |
||||
target="_blank" |
||||
href={getTokenTrackerLink( |
||||
address, |
||||
currentNetwork, |
||||
null, |
||||
null, |
||||
rpcPrefs, |
||||
)} |
||||
rel="noopener noreferrer" |
||||
> |
||||
{getEnvironmentType() === ENVIRONMENT_TYPE_POPUP |
||||
? shortenAddress(address) |
||||
: address} |
||||
</a> |
||||
</Typography> |
||||
</Box> |
||||
</Box> |
||||
</Box> |
||||
</> |
||||
); |
||||
} |
||||
|
||||
CollectibleDetails.propTypes = { |
||||
collectible: PropTypes.object, |
||||
}; |
@ -1,23 +0,0 @@ |
||||
import React from 'react'; |
||||
import CollectibleDetails from './collectible-details'; |
||||
|
||||
export default { |
||||
title: 'Components/App/CollectibleDetails', |
||||
id: __filename, |
||||
}; |
||||
|
||||
export const basic = () => { |
||||
const collectible = { |
||||
name: 'Catnip Spicywright', |
||||
tokenId: '1124157', |
||||
address: '0x06012c8cf97bead5deae237070f9587f8e7a266d', |
||||
image: './images/catnip-spicywright.png', |
||||
description: |
||||
"Good day. My name is Catnip Spicywight, which got me teased a lot in high school. If I want to put low fat mayo all over my hamburgers, I shouldn't have to answer to anyone about it, am I right? One time I beat Arlene in an arm wrestle.", |
||||
}; |
||||
return ( |
||||
<div style={{ width: '420px' }}> |
||||
<CollectibleDetails collectible={collectible} /> |
||||
</div> |
||||
); |
||||
}; |
@ -1,61 +0,0 @@ |
||||
import React, { useContext, useState } from 'react'; |
||||
import PropTypes from 'prop-types'; |
||||
|
||||
import { I18nContext } from '../../../contexts/i18n'; |
||||
import { Menu, MenuItem } from '../../ui/menu'; |
||||
|
||||
const CollectibleOptions = ({ onRemove, onViewOnOpensea }) => { |
||||
const t = useContext(I18nContext); |
||||
const [ |
||||
collectibleOptionsButtonElement, |
||||
setCollectibleOptionsButtonElement, |
||||
] = useState(null); |
||||
const [collectibleOptionsOpen, setCollectibleOptionsOpen] = useState(false); |
||||
|
||||
return ( |
||||
<> |
||||
<button |
||||
className="fas fa-ellipsis-v collectible-options__button" |
||||
data-testid="collectible-options__button" |
||||
onClick={() => setCollectibleOptionsOpen(true)} |
||||
ref={setCollectibleOptionsButtonElement} |
||||
/> |
||||
{collectibleOptionsOpen ? ( |
||||
<Menu |
||||
anchorElement={collectibleOptionsButtonElement} |
||||
onHide={() => setCollectibleOptionsOpen(false)} |
||||
> |
||||
{onViewOnOpensea ? ( |
||||
<MenuItem |
||||
iconClassName="fas fa-qrcode" |
||||
data-testid="collectible-options__view-on-opensea" |
||||
onClick={() => { |
||||
setCollectibleOptionsOpen(false); |
||||
onViewOnOpensea(); |
||||
}} |
||||
> |
||||
{t('viewOnOpensea')} |
||||
</MenuItem> |
||||
) : null} |
||||
<MenuItem |
||||
iconClassName="fas fa-trash-alt collectible-options__icon" |
||||
data-testid="collectible-options__hide" |
||||
onClick={() => { |
||||
setCollectibleOptionsOpen(false); |
||||
onRemove(); |
||||
}} |
||||
> |
||||
{t('removeNFT')} |
||||
</MenuItem> |
||||
</Menu> |
||||
) : null} |
||||
</> |
||||
); |
||||
}; |
||||
|
||||
CollectibleOptions.propTypes = { |
||||
onRemove: PropTypes.func.isRequired, |
||||
onViewOnOpensea: PropTypes.func.isRequired, |
||||
}; |
||||
|
||||
export default CollectibleOptions; |
@ -1,26 +0,0 @@ |
||||
.collectible-details { |
||||
display: flex; |
||||
flex-direction: column; |
||||
|
||||
@media screen and (min-width: $break-large) { |
||||
display: flex; |
||||
flex-direction: row; |
||||
} |
||||
|
||||
&__address { |
||||
overflow-wrap: break-word; |
||||
} |
||||
} |
||||
|
||||
.collectible-options { |
||||
&__button { |
||||
font-size: $font-size-paragraph; |
||||
color: $Black-100; |
||||
background-color: inherit; |
||||
padding: 2px 0 2px 8px; |
||||
} |
||||
|
||||
&__icon { |
||||
font-weight: 900; |
||||
} |
||||
} |
@ -1,18 +0,0 @@ |
||||
.collectibles-items { |
||||
&__image { |
||||
border-radius: 0.625rem; |
||||
width: 100%; |
||||
height: 100%; |
||||
} |
||||
} |
||||
|
||||
.collection-icon { |
||||
border-radius: 50%; |
||||
width: 2rem; |
||||
height: 2rem; |
||||
padding: 0.5rem; |
||||
background: $ui-4; |
||||
color: $ui-white; |
||||
text-align: center; |
||||
line-height: 1; |
||||
} |
Loading…
Reference in new issue