-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Showing
19 changed files
with
457 additions
and
23 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
87 changes: 87 additions & 0 deletions
87
packages/browser-wallet/src/popup/popupX/pages/Nft/Nft.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
.nft-x { | ||
.owner { | ||
display: flex; | ||
justify-content: space-between; | ||
|
||
.label__main { | ||
color: $color-white; | ||
} | ||
} | ||
|
||
&__list { | ||
display: flex; | ||
flex-wrap: wrap; | ||
justify-content: space-between; | ||
gap: rem(7px); | ||
margin-top: rem(8px); | ||
|
||
&_item { | ||
display: flex; | ||
flex-direction: column; | ||
width: rem(160px); | ||
height: rem(192px); | ||
padding: rem(8px) rem(8px) rem(16px) rem(8px); | ||
border: unset; | ||
border-radius: rem(12px); | ||
background-color: $color-transaction-bg; | ||
|
||
&-img { | ||
width: 100%; | ||
border-radius: rem(8px); | ||
} | ||
|
||
.text__main_regular { | ||
width: 100%; | ||
margin-top: rem(8px); | ||
overflow: hidden; | ||
white-space: nowrap; | ||
text-overflow: ellipsis; | ||
text-align: left; | ||
} | ||
} | ||
} | ||
} | ||
|
||
.nft-details-x { | ||
.page__top_side { | ||
.button__icon { | ||
svg { | ||
height: rem(16px); | ||
width: rem(16px); | ||
} | ||
|
||
&:last-of-type { | ||
svg path { | ||
fill: $color-red-attention; | ||
} | ||
} | ||
} | ||
} | ||
|
||
.info-row { | ||
display: flex; | ||
justify-content: space-between; | ||
padding: rem(4px) 0; | ||
border-bottom: 1px solid $color-grey-3; | ||
|
||
&:nth-child(3) { | ||
border-bottom: unset; | ||
} | ||
|
||
.capture__main_small:last-child { | ||
color: $color-white; | ||
} | ||
} | ||
|
||
.details-img { | ||
margin-top: rem(12px); | ||
margin-bottom: rem(16px); | ||
border-radius: rem(16px); | ||
} | ||
} | ||
|
||
.nft-raw-x { | ||
.row.details .capture__main_small:first-child { | ||
text-transform: capitalize; | ||
} | ||
} |
66 changes: 66 additions & 0 deletions
66
packages/browser-wallet/src/popup/popupX/pages/Nft/Nft.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
import React from 'react'; | ||
import { useTranslation } from 'react-i18next'; | ||
import Page from '@popup/popupX/shared/Page'; | ||
import Text from '@popup/popupX/shared/Text'; | ||
import Button from '@popup/popupX/shared/Button'; | ||
import { displayNameAndSplitAddress, useSelectedCredential } from '@popup/shared/utils/account-helpers'; | ||
import Img from '@popup/shared/Img'; | ||
import { WalletCredential } from '@shared/storage/types'; | ||
import { useFlattenedAccountTokens } from '@popup/pages/Account/Tokens/utils'; | ||
import { getMetadataUnique } from '@shared/utils/token-helpers'; | ||
import { useNavigate } from 'react-router-dom'; | ||
import { relativeRoutes } from '@popup/popupX/constants/routes'; | ||
|
||
function useFilteredTokens(account: WalletCredential, unique: boolean) { | ||
const tokens = useFlattenedAccountTokens(account); | ||
return tokens.filter((t) => getMetadataUnique(t.metadata) === unique); | ||
} | ||
|
||
function NftList({ account }: { account: WalletCredential }) { | ||
const tokens = useFilteredTokens(account, true); | ||
const nav = useNavigate(); | ||
const navToDetails = (contractIndex: string, id: string) => | ||
nav(relativeRoutes.settings.nft.details.path.replace(':contractIndex', contractIndex).replace(':id', id)); | ||
|
||
return ( | ||
<div className="nft-x__list"> | ||
{tokens.map(({ contractIndex, id, metadata }) => ( | ||
<Button.Base | ||
key={`${contractIndex}.${id}`} | ||
onClick={() => navToDetails(contractIndex, id)} | ||
className="nft-x__list_item" | ||
> | ||
<Img | ||
className="nft-x__list_item-img" | ||
src={metadata.thumbnail?.url ?? metadata.display?.url} | ||
alt={metadata.name} | ||
withDefaults | ||
/> | ||
<Text.MainRegular>{metadata.name}</Text.MainRegular> | ||
</Button.Base> | ||
))} | ||
</div> | ||
); | ||
} | ||
|
||
export default function Nft() { | ||
const { t } = useTranslation('x', { keyPrefix: 'nft' }); | ||
const account = useSelectedCredential(); | ||
|
||
if (account === undefined) { | ||
return null; | ||
} | ||
|
||
return ( | ||
<Page className="nft-x"> | ||
<Page.Top heading={t('nft')} /> | ||
<Page.Main> | ||
<span className="owner"> | ||
<Text.Label>{t('owned')}</Text.Label> | ||
<Text.Capture>{t('on', { value: displayNameAndSplitAddress(account) })}</Text.Capture> | ||
</span> | ||
<NftList account={account} /> | ||
</Page.Main> | ||
</Page> | ||
); | ||
} |
90 changes: 90 additions & 0 deletions
90
packages/browser-wallet/src/popup/popupX/pages/Nft/NftDetails.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
import React from 'react'; | ||
import Page from '@popup/popupX/shared/Page'; | ||
import { useTranslation } from 'react-i18next'; | ||
import { useNavigate, useParams } from 'react-router-dom'; | ||
import { withSelectedCredential } from '@popup/popupX/shared/utils/hoc'; | ||
import { WalletCredential } from '@shared/storage/types'; | ||
import { useFlattenedAccountTokens } from '@popup/pages/Account/Tokens/utils'; | ||
import Button from '@popup/popupX/shared/Button'; | ||
import Code from '@assets/svgX/code.svg'; | ||
import EyeSlash from '@assets/svgX/eye-slash.svg'; | ||
import Text from '@popup/popupX/shared/Text'; | ||
import Img from '@popup/shared/Img'; | ||
import { contractBalancesFamily, removeTokenFromCurrentAccountAtom } from '@popup/store/token'; | ||
import { useAtomValue } from 'jotai'; | ||
import { useUpdateAtom } from 'jotai/utils'; | ||
import { relativeRoutes } from '@popup/popupX/constants/routes'; | ||
|
||
const SUB_INDEX = '0'; | ||
|
||
type Params = { | ||
contractIndex: string; | ||
id: string; | ||
}; | ||
|
||
function useSelectedToken(credential: WalletCredential) { | ||
const { contractIndex, id } = useParams<Params>(); | ||
const token = useFlattenedAccountTokens(credential).find((t) => t.contractIndex === contractIndex && t.id === id); | ||
return token; | ||
} | ||
|
||
function useRemoveToken() { | ||
const { contractIndex, id } = useParams<Params>(); | ||
const nav = useNavigate(); | ||
const removeToken = useUpdateAtom(removeTokenFromCurrentAccountAtom); | ||
if (!contractIndex || !id) return () => {}; | ||
|
||
return () => { | ||
removeToken({ contractIndex, tokenId: id }); | ||
nav(-1); | ||
}; | ||
} | ||
|
||
type InfoRowProps = { | ||
title: string; | ||
value?: string; | ||
}; | ||
|
||
function InfoRow({ title, value }: InfoRowProps) { | ||
return ( | ||
<span className="info-row"> | ||
<Text.Capture>{title}</Text.Capture> | ||
<Text.Capture>{value}</Text.Capture> | ||
</span> | ||
); | ||
} | ||
|
||
function NftDetails({ credential }: { credential: WalletCredential }) { | ||
const nav = useNavigate(); | ||
const { t } = useTranslation('x', { keyPrefix: 'nft' }); | ||
const token = useSelectedToken(credential); | ||
const removeToken = useRemoveToken(); | ||
const { contractIndex, id, metadata } = token || { id: '', contractIndex: '' }; | ||
const balancesAtom = contractBalancesFamily(credential?.address ?? '', token?.contractIndex ?? ''); | ||
const balance = useAtomValue(balancesAtom)[id]; | ||
|
||
const navToRaw = () => nav(relativeRoutes.settings.nft.details.raw.path); | ||
|
||
return ( | ||
<Page className="nft-details-x"> | ||
<Page.Top heading={metadata?.name}> | ||
<Button.Icon icon={<Code />} onClick={navToRaw} /> | ||
<Button.Icon icon={<EyeSlash />} onClick={removeToken} /> | ||
</Page.Top> | ||
<Page.Main> | ||
<InfoRow title={t('ownership')} value={balance === 0n ? t('unownedUnique') : t('ownedUnique')} /> | ||
<InfoRow title={t('contract')} value={`${contractIndex}, ${SUB_INDEX}`} /> | ||
<InfoRow title={t('tokenId')} value={id} /> | ||
<Img | ||
className="details-img" | ||
src={metadata?.thumbnail?.url ?? metadata?.display?.url} | ||
alt={metadata?.name} | ||
withDefaults | ||
/> | ||
<Text.Capture>{metadata?.description}</Text.Capture> | ||
</Page.Main> | ||
</Page> | ||
); | ||
} | ||
|
||
export default withSelectedCredential(NftDetails); |
48 changes: 48 additions & 0 deletions
48
packages/browser-wallet/src/popup/popupX/pages/Nft/NftRaw.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import React from 'react'; | ||
import Page from '@popup/popupX/shared/Page'; | ||
import { WalletCredential } from '@shared/storage/types'; | ||
import { useParams } from 'react-router-dom'; | ||
import { useFlattenedAccountTokens } from '@popup/pages/Account/Tokens/utils'; | ||
import { withSelectedCredential } from '@popup/popupX/shared/utils/hoc'; | ||
import { useTranslation } from 'react-i18next'; | ||
import Button from '@popup/popupX/shared/Button'; | ||
import Copy from '@assets/svgX/copy.svg'; | ||
import { copyToClipboard } from '@popup/popupX/shared/utils/helpers'; | ||
import Card from '@popup/popupX/shared/Card'; | ||
|
||
type Params = { | ||
contractIndex: string; | ||
id: string; | ||
}; | ||
|
||
function useSelectedToken(credential: WalletCredential) { | ||
const { contractIndex, id } = useParams<Params>(); | ||
const token = useFlattenedAccountTokens(credential).find((t) => t.contractIndex === contractIndex && t.id === id); | ||
return token; | ||
} | ||
|
||
function NftRaw({ credential }: { credential: WalletCredential }) { | ||
const { t } = useTranslation('x', { keyPrefix: 'nft' }); | ||
const token = useSelectedToken(credential); | ||
const metadata = token?.metadata || {}; | ||
|
||
return ( | ||
<Page className="nft-raw-x"> | ||
<Page.Top heading={t('rawMetadata')}> | ||
<Button.Icon | ||
icon={<Copy />} | ||
onClick={() => copyToClipboard(JSON.stringify(token?.metadata, null, 2))} | ||
/> | ||
</Page.Top> | ||
<Page.Main> | ||
<Card> | ||
{Object.entries(metadata).map(([k, v]) => ( | ||
<Card.RowDetails key={k} title={k} value={JSON.stringify(v)} /> | ||
))} | ||
</Card> | ||
</Page.Main> | ||
</Page> | ||
); | ||
} | ||
|
||
export default withSelectedCredential(NftRaw); |
Oops, something went wrong.