From 4a16372bf7887bd3cf6b73c8e08f633102e90301 Mon Sep 17 00:00:00 2001 From: lelenei <72531217+lelenei@users.noreply.github.com> Date: Mon, 27 Sep 2021 14:12:29 +0800 Subject: [PATCH 1/7] feat: save avatar in json --- .../InjectedComponents/NFT/gun/db.ts | 48 ++++++++++++++ .../InjectedComponents/NFT/gun/gun.ts | 64 ++++++++++++++++++ .../InjectedComponents/NFT/gun/index.ts | 66 +------------------ .../InjectedComponents/NFT/types.ts | 10 +-- .../injection/NFT/NFTAvatarInTwitter.tsx | 24 +------ .../injection/NFT/profileNFTAvatar.tsx | 16 +---- .../twitter.com/utils/updateAvatarImage.ts | 54 --------------- packages/maskbook/src/utils/messages.ts | 2 - 8 files changed, 121 insertions(+), 163 deletions(-) create mode 100644 packages/maskbook/src/components/InjectedComponents/NFT/gun/db.ts create mode 100644 packages/maskbook/src/components/InjectedComponents/NFT/gun/gun.ts delete mode 100644 packages/maskbook/src/social-network-adaptor/twitter.com/utils/updateAvatarImage.ts diff --git a/packages/maskbook/src/components/InjectedComponents/NFT/gun/db.ts b/packages/maskbook/src/components/InjectedComponents/NFT/gun/db.ts new file mode 100644 index 000000000000..2ef8597ab020 --- /dev/null +++ b/packages/maskbook/src/components/InjectedComponents/NFT/gun/db.ts @@ -0,0 +1,48 @@ +import { delay } from '@masknet/shared-base' +import { AvatarMetaDB, NFT_AVATAR_JSON_SERVER } from '../types' + +const cache = new Map<'avatardb', Promise>() + +async function fetchData() { + const response = await fetch(NFT_AVATAR_JSON_SERVER) + const json = await response.json() + return json +} + +async function _fetch() { + let f = cache.get('avatardb') + if (!f) { + f = fetchData() + cache.set('avatardb', f) + } + + const json = await f + + return json +} + +export async function getNFTAvatar(userId: string) { + const db = (await _fetch()).filter((x) => x.userId === userId) + if (db?.length === 0) return + + return db[0] +} + +export async function setOrClearAvatar(userId: string, avatar?: AvatarMetaDB) { + await delay(500) +} + +export async function getNFTAvatars() { + const AvatarDB = await _fetch() + return AvatarDB +} + +export async function saveNFTAvatar(userId: string, avatarId: string, address: string, tokenId: string) { + await delay(500) + return { + userId, + avatarId, + address, + tokenId, + } +} diff --git a/packages/maskbook/src/components/InjectedComponents/NFT/gun/gun.ts b/packages/maskbook/src/components/InjectedComponents/NFT/gun/gun.ts new file mode 100644 index 000000000000..6deaaa219731 --- /dev/null +++ b/packages/maskbook/src/components/InjectedComponents/NFT/gun/gun.ts @@ -0,0 +1,64 @@ +import { AvatarMetaDB, NFT_AVATAR_SERVER } from '../types' + +const NFTAvatarCache = new Map() +async function getAvatarGun() { + // TODO: do not call gun in SNS adaptor. + const { gun2 } = await import('../../../../network/gun/version.2') + return { gun2 } +} + +async function getNFTAvatar(userId: string) { + const avatar = NFTAvatarCache.get(userId) + if (!avatar) { + NFTAvatarCache.set( + userId, + await ( + await getAvatarGun() + ).gun2 + .get(NFT_AVATAR_SERVER) + // @ts-expect-error + .get(userId).then!(), + ) + } + + return NFTAvatarCache.get(userId) +} + +async function setOrClearAvatar(userId: string, avatar?: AvatarMetaDB) { + await ( + await getAvatarGun() + ).gun2 + .get(NFT_AVATAR_SERVER) + // @ts-expect-error + .get(userId) + // @ts-expect-error + .put(avatar ? avatar : null).then!() +} + +async function getNFTAvatars() { + const NFTAvatarNodes = + (await ( + await getAvatarGun() + ).gun2 //@ts-expect-error + .get(NFT_AVATAR_SERVER).then!()) || [] + console.log(NFTAvatarNodes) + + const NFTAvatarKeys = Object.keys(NFTAvatarNodes).filter((x) => x !== '_') + const resultPromise = NFTAvatarKeys.map((key) => getNFTAvatar(key)) + const result = (await Promise.all(resultPromise)).filter((x) => x) as AvatarMetaDB[] + return result +} + +async function saveNFTAvatar(userId: string, avatarId: string, address: string, tokenId: string) { + const avatarMeta: AvatarMetaDB = { + userId, + address, + tokenId, + avatarId, + } + + await setOrClearAvatar(userId) + + await setOrClearAvatar(userId, avatarMeta) + return avatarMeta +} diff --git a/packages/maskbook/src/components/InjectedComponents/NFT/gun/index.ts b/packages/maskbook/src/components/InjectedComponents/NFT/gun/index.ts index b0f391c51ca0..1beb455f5e39 100644 --- a/packages/maskbook/src/components/InjectedComponents/NFT/gun/index.ts +++ b/packages/maskbook/src/components/InjectedComponents/NFT/gun/index.ts @@ -1,65 +1 @@ -import type { AvatarMetaDB } from '../types' -import { getNFT } from '../utils' - -const NFTAvatarCache = new Map() -async function getAvatarGun() { - // TODO: do not call gun in SNS adaptor. - const { gun2 } = await import('../../../../network/gun/version.2') - return { gun2 } -} - -export async function getNFTAvatar(userId: string) { - if (NFTAvatarCache.has(userId)) return NFTAvatarCache.get(userId) - const avatarDB = await ( - await getAvatarGun() - ).gun2 - .get('com.maskbook.nft.avatar') - // @ts-expect-error - .get(userId).then!() - - NFTAvatarCache.set(userId, avatarDB) - return avatarDB as AvatarMetaDB -} - -export async function setOrClearAvatar(userId: string, avatar?: AvatarMetaDB) { - await ( - await getAvatarGun() - ).gun2 - .get('com.maskbook.nft.avatar') - // @ts-expect-error - .get(userId) - // @ts-expect-error - .put(avatar ? avatar : null).then!() -} - -export async function getNFTAvatars() { - const NFTAvatarNodes = - (await ( - await getAvatarGun() - ).gun2 //@ts-expect-error - .get('com.maskbook.nft.avatar').then!()) || [] - const NFTAvatarKeys = Object.keys(NFTAvatarNodes).filter((x) => x !== '_') - const resultPromise = NFTAvatarKeys.map((key) => getNFTAvatar(key)) - const result = (await Promise.all(resultPromise)).filter((x) => x) as AvatarMetaDB[] - - return result -} - -export async function saveNFTAvatar(userId: string, avatarId: string, address: string, tokenId: string) { - const { name, symbol, amount, image } = await getNFT(address, tokenId) - const avatarMeta: AvatarMetaDB = { - name, - amount, - symbol, - image, - userId, - address, - tokenId, - avatarId, - } - - await setOrClearAvatar(userId) - - await setOrClearAvatar(userId, avatarMeta) - return avatarMeta -} +export * from './db' diff --git a/packages/maskbook/src/components/InjectedComponents/NFT/types.ts b/packages/maskbook/src/components/InjectedComponents/NFT/types.ts index fd9cb6fcc927..a11c4c193d5c 100644 --- a/packages/maskbook/src/components/InjectedComponents/NFT/types.ts +++ b/packages/maskbook/src/components/InjectedComponents/NFT/types.ts @@ -1,12 +1,8 @@ export interface AvatarMetaDB { userId: string tokenId: string - amount: string - image?: string - name?: string address: string - avatarId?: string - symbol: string + avatarId: string } export interface NFT { @@ -15,3 +11,7 @@ export interface NFT { name: string image: string } + +export const NFT_AVATAR_SERVER = 'com.maskbook.nft.avatar' +export const NFT_AVATAR_JSON_SERVER = + 'https://raw.githubusercontent.com/DimensionDev/Maskbook-Configuration/master/development/com.maskbook.avatar.json' diff --git a/packages/maskbook/src/social-network-adaptor/twitter.com/injection/NFT/NFTAvatarInTwitter.tsx b/packages/maskbook/src/social-network-adaptor/twitter.com/injection/NFT/NFTAvatarInTwitter.tsx index 3e2f7e65f9f8..a5bbca8e8082 100644 --- a/packages/maskbook/src/social-network-adaptor/twitter.com/injection/NFT/NFTAvatarInTwitter.tsx +++ b/packages/maskbook/src/social-network-adaptor/twitter.com/injection/NFT/NFTAvatarInTwitter.tsx @@ -5,10 +5,9 @@ import { makeStyles, useSnackbar } from '@masknet/theme' import { useState, useEffect, useCallback } from 'react' import { useCurrentVisitingIdentity } from '../../../../components/DataSource/useActivatedUI' -import { updateAvatarImage } from '../../utils/updateAvatarImage' import { getAvatarId } from '../../utils/user' import { NFTBadge } from '../../../../components/InjectedComponents/NFT/NFTBadge' -import { saveNFTAvatar, setOrClearAvatar } from '../../../../components/InjectedComponents/NFT/gun' +import { saveNFTAvatar } from '../../../../components/InjectedComponents/NFT/gun' import { useNFTAvatar } from '../../../../components/InjectedComponents/NFT/hooks' import type { AvatarMetaDB } from '../../../../components/InjectedComponents/NFT/types' @@ -42,22 +41,16 @@ interface NFTAvatarInTwitterProps {} function NFTAvatarInTwitter(props: NFTAvatarInTwitterProps) { const { classes } = useStyles() const identity = useCurrentVisitingIdentity() - const [amount, setAmount] = useState('') const _avatar = useNFTAvatar(identity.identifier.userId) const { enqueueSnackbar } = useSnackbar() const [avatar, setAvatar] = useState(_avatar) - const getParentDom = () => - searchTwitterAvatarSelector().querySelector('div > :nth-child(2) > div').evaluate() + const [avatarId, setAvatarId] = useState('') const onUpdate = useCallback( (data: NFTAvatarEvent) => { saveNFTAvatar(data.userId, data.avatarId, data.address, data.tokenId) .then((avatar: AvatarMetaDB) => { - const parent = getParentDom() - if (!parent) return - updateAvatarImage(parent, avatar.image ?? '') - setAmount(avatar.amount) setAvatar(avatar) }) .catch((error: Error) => { @@ -80,21 +73,8 @@ function NFTAvatarInTwitter(props: NFTAvatarInTwitterProps) { useEffect(() => { setAvatar(_avatar) - const parent = getParentDom() - if (!parent) return - if (!_avatar) return - setAmount(_avatar?.amount ?? '0') - updateAvatarImage(parent, _avatar?.image ?? '') }, [_avatar]) - const onClick = async () => { - const parent = getParentDom() - if (!parent) return - await setOrClearAvatar(identity.identifier.userId) - updateAvatarImage(parent) - setAvatar(undefined) - } - if (!avatar) return null return ( <> diff --git a/packages/maskbook/src/social-network-adaptor/twitter.com/injection/NFT/profileNFTAvatar.tsx b/packages/maskbook/src/social-network-adaptor/twitter.com/injection/NFT/profileNFTAvatar.tsx index b4ca05fc6abf..edd33c4c9655 100644 --- a/packages/maskbook/src/social-network-adaptor/twitter.com/injection/NFT/profileNFTAvatar.tsx +++ b/packages/maskbook/src/social-network-adaptor/twitter.com/injection/NFT/profileNFTAvatar.tsx @@ -8,12 +8,7 @@ import { useNFTAvatar } from '../../../../components/InjectedComponents/NFT/hook import { NFTAvatar } from '../../../../components/InjectedComponents/NFT/NFTAvatar' import { activatedSocialNetworkUI } from '../../../../social-network' import { createReactRootShadowed, Flags, MaskMessage, NFTAvatarEvent, startWatch } from '../../../../utils' -import { - searchProfileAvatarParentSelector, - searchProfileAvatarSelector, - searchProfileSaveSelector, -} from '../../utils/selector' -import { updateAvatarImage } from '../../utils/updateAvatarImage' +import { searchProfileAvatarSelector, searchProfileSaveSelector } from '../../utils/selector' import { getAvatar, getAvatarId, getTwitterId } from '../../utils/user' export async function injectProfileNFTAvatarInTwitter(signal: AbortSignal) { @@ -56,20 +51,13 @@ function NFTAvatarInTwitter(props: NFTAvatarInTwitterProps) { const [avatarEvent, setAvatarEvent] = useState({} as NFTAvatarEvent) const onChange = useCallback(async (token: ERC721TokenDetailed) => { - const parent = searchProfileAvatarParentSelector() - if (!parent) return - const avatarId = getAvatarId(getAvatar()) setAvatarEvent({ userId: twitterId, tokenId: token.tokenId, address: token.contractDetailed.address, - image: token.info.image ?? '', avatarId, - amount: '0', }) - - updateAvatarImage(parent, token.info.image) }, []) const handler = () => { @@ -80,8 +68,6 @@ function NFTAvatarInTwitter(props: NFTAvatarInTwitterProps) { useEffect(() => { if (!Flags.nft_avatar_enabled) return setTwitterId(getTwitterId()) - const parent = searchProfileAvatarParentSelector() - if (parent && avatar) updateAvatarImage(parent, avatar.image) }, [avatar]) useEffect(() => { diff --git a/packages/maskbook/src/social-network-adaptor/twitter.com/utils/updateAvatarImage.ts b/packages/maskbook/src/social-network-adaptor/twitter.com/utils/updateAvatarImage.ts deleted file mode 100644 index 484f27732576..000000000000 --- a/packages/maskbook/src/social-network-adaptor/twitter.com/utils/updateAvatarImage.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { Flags } from '../../../utils' - -export function updateAvatarImage(parent: HTMLElement, image?: string) { - if (!Flags.nft_avatar_enabled) { - return - } - - return - /* - if (!image) { - recoverAvatar(parent) - return - } - - const avatar = parent?.firstChild as HTMLDivElement - if (avatar) { - if (!avatar.hasAttribute('avatar')) { - avatar.setAttribute('avatar', avatar.style.backgroundImage) - } - avatar.style.backgroundImage = `url(${new URL(image, import.meta.url)})` - } - const ele = parent.lastChild as HTMLDivElement - - if (ele) { - if (!ele.hasAttribute('avatar')) { - ele.setAttribute('avatar', ele.getAttribute('src') ?? '') - } - ele.setAttribute('src', `url(${new URL(image, import.meta.url)})`) - } - */ -} - -function recoverAvatar(parent: HTMLElement) { - const avatar = parent.firstChild as HTMLDivElement - if (avatar) { - if (avatar.hasAttribute('avatar')) { - avatar.style.backgroundImage = avatar.getAttribute('avatar') ?? '' - avatar.removeAttribute('avatar') - } - } - - const image = parent.lastChild as HTMLDivElement - if (image) { - if (image.hasAttribute('avatar')) { - image.setAttribute('src', image.getAttribute('avatar') ?? '') - image.removeAttribute('avatar') - } - } -} - -export function updateAvatarFromDB(parent?: HTMLElement, twitterId?: string) { - if (!parent || !twitterId) return - return null -} diff --git a/packages/maskbook/src/utils/messages.ts b/packages/maskbook/src/utils/messages.ts index 2e7f9a0b528b..c71b730098f0 100644 --- a/packages/maskbook/src/utils/messages.ts +++ b/packages/maskbook/src/utils/messages.ts @@ -38,8 +38,6 @@ export interface ProfileNFTsPageEvent { export interface NFTAvatarEvent { userId: string tokenId: string - image?: string - amount: string address: string avatarId: string } From 908363899da0691f4e2441990a65bfa19efe5474 Mon Sep 17 00:00:00 2001 From: lelenei <72531217+lelenei@users.noreply.github.com> Date: Mon, 27 Sep 2021 15:03:16 +0800 Subject: [PATCH 2/7] fix: cache fetch result --- .../InjectedComponents/NFT/gun/db.ts | 28 ++++++++++++++----- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/packages/maskbook/src/components/InjectedComponents/NFT/gun/db.ts b/packages/maskbook/src/components/InjectedComponents/NFT/gun/db.ts index 2ef8597ab020..b3bf1e67b1f8 100644 --- a/packages/maskbook/src/components/InjectedComponents/NFT/gun/db.ts +++ b/packages/maskbook/src/components/InjectedComponents/NFT/gun/db.ts @@ -1,23 +1,37 @@ import { delay } from '@masknet/shared-base' import { AvatarMetaDB, NFT_AVATAR_JSON_SERVER } from '../types' -const cache = new Map<'avatardb', Promise>() +const EXPIRED_TIME = 5 * 60 +const cache = new Map<'avatar', [number, Promise]>() async function fetchData() { const response = await fetch(NFT_AVATAR_JSON_SERVER) - const json = await response.json() + if (!response.ok) return [] + const json = (await response.json()) as AvatarMetaDB[] return json } async function _fetch() { - let f = cache.get('avatardb') - if (!f) { + const c = cache.get('avatar') + let f, json + if (c) { + f = c[1] + if (!f) { + f = fetchData() + cache.set('avatar', [Date.now(), f]) + } + if (Date.now() - c[0] >= EXPIRED_TIME) { + json = await f + f = fetchData() + cache.set('avatar', [Date.now(), f]) + return json + } + } else { f = fetchData() - cache.set('avatardb', f) + cache.set('avatar', [Date.now(), f]) } - const json = await f - + json = await f return json } From 627a189ea0749efaaae99628850f9cf3de3469a8 Mon Sep 17 00:00:00 2001 From: lelenei <72531217+lelenei@users.noreply.github.com> Date: Mon, 27 Sep 2021 15:34:10 +0800 Subject: [PATCH 3/7] refactor: json url --- .../maskbook/src/components/InjectedComponents/NFT/types.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/maskbook/src/components/InjectedComponents/NFT/types.ts b/packages/maskbook/src/components/InjectedComponents/NFT/types.ts index a11c4c193d5c..ba6dfcba9ead 100644 --- a/packages/maskbook/src/components/InjectedComponents/NFT/types.ts +++ b/packages/maskbook/src/components/InjectedComponents/NFT/types.ts @@ -13,5 +13,4 @@ export interface NFT { } export const NFT_AVATAR_SERVER = 'com.maskbook.nft.avatar' -export const NFT_AVATAR_JSON_SERVER = - 'https://raw.githubusercontent.com/DimensionDev/Maskbook-Configuration/master/development/com.maskbook.avatar.json' +export const NFT_AVATAR_JSON_SERVER = 'https://dimensiondev.github.io/Maskbook-Configuration/com.maskbook.avatar.json' From 1e3fedd7e30edb7531cf484c69734f38bc2c9ebc Mon Sep 17 00:00:00 2001 From: lelenei <72531217+lelenei@users.noreply.github.com> Date: Mon, 27 Sep 2021 15:40:16 +0800 Subject: [PATCH 4/7] fix: expire time --- .../maskbook/src/components/InjectedComponents/NFT/gun/db.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/maskbook/src/components/InjectedComponents/NFT/gun/db.ts b/packages/maskbook/src/components/InjectedComponents/NFT/gun/db.ts index b3bf1e67b1f8..7ee2f28e8e30 100644 --- a/packages/maskbook/src/components/InjectedComponents/NFT/gun/db.ts +++ b/packages/maskbook/src/components/InjectedComponents/NFT/gun/db.ts @@ -1,7 +1,7 @@ import { delay } from '@masknet/shared-base' import { AvatarMetaDB, NFT_AVATAR_JSON_SERVER } from '../types' -const EXPIRED_TIME = 5 * 60 +const EXPIRED_TIME = 5 * 60 * 1000 const cache = new Map<'avatar', [number, Promise]>() async function fetchData() { From f91955a1837ed715325975c4135322dd299b09d2 Mon Sep 17 00:00:00 2001 From: lelenei <72531217+lelenei@users.noreply.github.com> Date: Mon, 27 Sep 2021 16:58:19 +0800 Subject: [PATCH 5/7] fix: remove bind in dashboard --- .../DashboardDialogs/Avatar/confirm.tsx | 50 --- .../DashboardDialogs/Avatar/index.tsx | 135 -------- .../DashboardRouters/NFTAvatarList.tsx | 319 ------------------ .../DashboardRouters/Settings.tsx | 21 -- .../src/extension/options-page/Route.ts | 1 - .../src/extension/options-page/index.tsx | 2 - packages/maskbook/src/locales/en-US.json | 7 +- packages/maskbook/src/locales/qya-AA.json | 3 - 8 files changed, 1 insertion(+), 537 deletions(-) delete mode 100644 packages/maskbook/src/extension/options-page/DashboardDialogs/Avatar/confirm.tsx delete mode 100644 packages/maskbook/src/extension/options-page/DashboardDialogs/Avatar/index.tsx delete mode 100644 packages/maskbook/src/extension/options-page/DashboardRouters/NFTAvatarList.tsx diff --git a/packages/maskbook/src/extension/options-page/DashboardDialogs/Avatar/confirm.tsx b/packages/maskbook/src/extension/options-page/DashboardDialogs/Avatar/confirm.tsx deleted file mode 100644 index 568706dc62bd..000000000000 --- a/packages/maskbook/src/extension/options-page/DashboardDialogs/Avatar/confirm.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import { Box, Button } from '@material-ui/core' -import { useI18N } from '../../../../utils' -import { DashboardDialogCore, DashboardDialogWrapper, WrappedDialogProps } from '../Base' -import { makeStyles } from '@masknet/theme' -import StorageIcon from '@material-ui/icons/Storage' -import type { AvatarMetaDB } from '../../../../components/InjectedComponents/NFT/types' - -const useStyles = makeStyles()({ - root: { - marginBottom: 0, - }, - icon: { - height: 64, - width: 64, - }, -}) - -interface AvatarMetaDBProps { - avatar: AvatarMetaDB -} -export function DashboardUnbindNFTAvatarDialog( - props: WrappedDialogProps void }>, -) { - const { t } = useI18N() - const { classes } = useStyles() - const avatar = props.ComponentProps?.avatar - const onClick = () => { - props.ComponentProps?.onDeleted() - props.onClose() - } - if (!avatar) return null - return ( - - } - iconColor="#f76969" - primary={t('unbind_nft_avatar')} - secondary={t('delete_nft_avatar', { userId: avatar.userId })} - footer={ - - - - } - /> - - ) -} diff --git a/packages/maskbook/src/extension/options-page/DashboardDialogs/Avatar/index.tsx b/packages/maskbook/src/extension/options-page/DashboardDialogs/Avatar/index.tsx deleted file mode 100644 index ef1315530b84..000000000000 --- a/packages/maskbook/src/extension/options-page/DashboardDialogs/Avatar/index.tsx +++ /dev/null @@ -1,135 +0,0 @@ -import { Box, Button, Typography } from '@material-ui/core' -import { useI18N } from '../../../../utils' -import { DashboardDialogCore, DashboardDialogWrapper, WrappedDialogProps } from '../Base' -import { makeStyles } from '@masknet/theme' -import StorageIcon from '@material-ui/icons/Storage' -import { InputBox } from '../../DashboardComponents/InputBox' -import { useCallback, useState } from 'react' - -const useStyles = makeStyles()({ - root: { - marginBottom: 0, - }, - table: { - paddingLeft: 28, - paddingRight: 28, - marginTop: 2, - marginBottom: 28, - }, - buttonText: { - color: '#fff', - }, - message: { - '&:before': { - content: '""', - borderLeft: `2px solid`, - paddingRight: 2, - }, - alignSelf: 'self-start', - }, - icon: { - height: 64, - width: 64, - }, -}) - -export function DashboardBindNFTAvatarDialog( - props: WrappedDialogProps<{ onAdd: (userId: string, avatarId: string, address: string, tokenId: string) => void }>, -) { - const { t } = useI18N() - const { classes } = useStyles() - const [message, setMessage] = useState('') - const [userId, setUserId] = useState('') - const [avatarId, setAvatarId] = useState('') - const [address, setAddress] = useState('') - const [tokenId, setTokenId] = useState('') - - const _onAdd = useCallback(() => { - if (!userId) { - setMessage('Please Input User ID') - return - } - if (!avatarId) { - setMessage('Please Input Avatar ID') - return - } - if (!address) { - setMessage('Please Input Contract address') - return - } - if (!tokenId) { - setMessage('Please Input Token ID') - return - } - - props.ComponentProps?.onAdd(userId, avatarId, address, tokenId) - props.onClose() - }, [userId, avatarId, address, tokenId]) - - return ( - - } - iconColor="#699CF7" - primary={t('bind_nft_avatar')} - footer={ - * ': { - margin: 1, - }, - }}> - { - setUserId(val) - setMessage('') - }} - /> - { - setAvatarId(val) - setMessage('') - }} - /> - { - setAddress(val) - setMessage('') - }} - /> - { - setTokenId(val) - setMessage('') - }} - /> - - {message ? ( - - {message} - - ) : null} - - - } - /> - - ) -} diff --git a/packages/maskbook/src/extension/options-page/DashboardRouters/NFTAvatarList.tsx b/packages/maskbook/src/extension/options-page/DashboardRouters/NFTAvatarList.tsx deleted file mode 100644 index 0b4e502c25dd..000000000000 --- a/packages/maskbook/src/extension/options-page/DashboardRouters/NFTAvatarList.tsx +++ /dev/null @@ -1,319 +0,0 @@ -import { FormattedAddress } from '@masknet/shared' -import { makeStyles, useSnackbar } from '@masknet/theme' -import { resolveOpenSeaLink } from '@masknet/web3-shared' -import { - Box, - Button, - IconButton, - Link, - Paper, - Skeleton, - Table, - TableBody, - TableCell, - TableContainer, - TableHead, - TableRow, - ThemeProvider, - Typography, -} from '@material-ui/core' -import CancelOutlinedIcon from '@material-ui/icons/CancelOutlined' - -import { extendsTheme, useI18N } from '../../../utils' -import { DashboardBindNFTAvatarDialog } from '../DashboardDialogs/Avatar' -import { useModal } from '../DashboardDialogs/Base' -import DashboardRouterContainer from './Container' -import LaunchIcon from '@material-ui/icons/Launch' -import urlcat from 'urlcat' -import { useCurrentIdentity } from '../../../components/DataSource/useActivatedUI' -import { DashboardUnbindNFTAvatarDialog } from '../DashboardDialogs/Avatar/confirm' -import { useCallback, useEffect, useState } from 'react' -import { remove } from 'lodash-es' -import { useNFTAvatars } from '../../../components/InjectedComponents/NFT/hooks' -import type { AvatarMetaDB } from '../../../components/InjectedComponents/NFT/types' -import { saveNFTAvatar, setOrClearAvatar } from '../../../components/InjectedComponents/NFT/gun' - -const settingsTheme = extendsTheme((theme) => ({ - wrapper: { - padding: theme.spacing(0, 3), - }, - typography: { - body1: { - lineHeight: 1.75, - }, - }, - components: { - MuiPaper: { - styleOverrides: { - rounded: { - borderRadius: 12, - }, - }, - }, - MuiCard: { - styleOverrides: { - root: { - overflow: 'visible', - }, - }, - }, - MuiOutlinedInput: { - styleOverrides: { - input: { - paddingTop: theme.spacing(1), - paddingBottom: theme.spacing(1), - }, - }, - }, - button: {}, - }, -})) - -export function DashboardNFTAvatarsRouter() { - const { t } = useI18N() - return ( - - - - - - ) -} - -const useStyles = makeStyles()((theme) => ({ - root: {}, - list: { - height: '100%', - overflowY: 'auto', - }, - addToken: { - paddingTop: theme.spacing(1), - textAlign: 'right', - paddingRight: theme.spacing(4), - }, - title: { - whiteSpace: 'nowrap', - }, - cell: {}, - tokenId: { - width: 100, - textOverflow: 'ellipsis', - overflow: 'hidden', - }, -})) - -function NFTAvatarWhitelist() { - const { t } = useI18N() - const { classes } = useStyles() - - const { value: _avatars, loading } = useNFTAvatars() - const { enqueueSnackbar } = useSnackbar() - const [avatars, setAvatars] = useState([]) - - const onAdd = useCallback( - async (userId: string, avatarId: string, address: string, tokenId: string) => { - const avatar = await saveNFTAvatar(userId, avatarId, address, tokenId) - - enqueueSnackbar('Add Success', { variant: 'success' }) - setAvatars((v) => [...v, avatar]) - }, - [saveNFTAvatar, enqueueSnackbar], - ) - - const [bindNFTAvatarDialog, openBindNFTAvatarDialog] = useModal(DashboardBindNFTAvatarDialog, { onAdd }) - const onDeleted = useCallback( - async (avatar) => { - setAvatars((x) => remove([...x], (i) => i.userId !== avatar.userId)) - setOrClearAvatar(avatar.userId) - .then(() => { - enqueueSnackbar('Remove Success', { variant: 'success' }) - }) - .catch((error) => enqueueSnackbar(error.message, { variant: 'error' })) - }, - [setOrClearAvatar], - ) - - useEffect(() => { - if (!_avatars) return - setAvatars(_avatars) - }, [_avatars]) - - return ( - - - - - - - - - - - - User ID - - - - - Avatar ID - - - - - Contract Address - - - - - Token ID - - - - - - - - - {loading ? ( - - ) : ( - avatars - ?.filter((x) => x) - .map((avatar, i) => ( - - )) - )} - -
-
-
- {bindNFTAvatarDialog} -
- ) -} - -interface NFTAvatarWhitelistLineProps { - avatar: AvatarMetaDB - onDeleted: (avatar: AvatarMetaDB) => void -} -function NFTAvatarWhitelistLine(props: NFTAvatarWhitelistLineProps) { - const { classes } = useStyles() - const { avatar, onDeleted } = props - - const _onDeleted = () => onDeleted(avatar) - - const [unbindNFTAvatarDialog, openUnbindNFTAvatarDialog] = useModal(DashboardUnbindNFTAvatarDialog, { - avatar, - onDeleted: _onDeleted, - }) - if (!avatar) return null - return ( - - - - - - - - - {avatar.avatarId} - - - - - - - - - - {avatar.tokenId} - - - - - - - - {unbindNFTAvatarDialog} - - ) -} - -function LoadingStatus() { - const { classes } = useStyles() - return ( - <> - {Array.from({ length: 3 }) - .fill(0) - .map((_, i) => ( - - - - - - - - - - - - - - - - - - ))} - - ) -} - -interface FormatNFTContractProps { - address: string - size: number - tokenId: string -} - -function FormatNFTContract(props: FormatNFTContractProps) { - const { address, size, tokenId } = props - - if (!tokenId || !address) return null - return ( - - - - - ) -} - -interface FormatLinkUserProps { - userId: string -} - -function FormatLinkUser({ userId }: FormatLinkUserProps) { - const currentIdentity = useCurrentIdentity() - - if (!userId) return null - return ( - - {userId} - - ) -} diff --git a/packages/maskbook/src/extension/options-page/DashboardRouters/Settings.tsx b/packages/maskbook/src/extension/options-page/DashboardRouters/Settings.tsx index eda716ec4492..277a49c8fa0e 100644 --- a/packages/maskbook/src/extension/options-page/DashboardRouters/Settings.tsx +++ b/packages/maskbook/src/extension/options-page/DashboardRouters/Settings.tsx @@ -50,9 +50,7 @@ import { useCurrentTradeProvider } from '../../../plugins/Trader/trending/useCur import { useCurrentDataProvider } from '../../../plugins/Trader/trending/useCurrentDataProvider' import { DataProvider, TradeProvider } from '@masknet/public-api' import { safeUnreachable } from '@dimensiondev/kit' -import StorageIcon from '@material-ui/icons/Storage' import { useHistory } from 'react-router-dom' -import { DashboardRoute } from '../Route' const useStyles = makeStyles()((theme) => ({ root: { @@ -288,25 +286,6 @@ export default function DashboardSettingsRouter() { - {Flags.nft_avatar_enabled ? ( - - - {t('settings_title_bind_nft_avatar')} - - - - } - primary="Bind NFT Avatar" - secondary="" - onClick={() => history.push(DashboardRoute.NFTAvatars)} - /> - - - - ) : null} - {t('settings_title_advanced_options')} diff --git a/packages/maskbook/src/extension/options-page/Route.ts b/packages/maskbook/src/extension/options-page/Route.ts index 95b043753f46..c7bb78be3638 100644 --- a/packages/maskbook/src/extension/options-page/Route.ts +++ b/packages/maskbook/src/extension/options-page/Route.ts @@ -6,7 +6,6 @@ export enum DashboardRoute { Settings = '/settings', Plugins = '/plugins', Setup = '/setup', - NFTAvatars = '/NFTAvatars', } export enum DashboardWalletRoute { diff --git a/packages/maskbook/src/extension/options-page/index.tsx b/packages/maskbook/src/extension/options-page/index.tsx index 4531fe016fc7..cced3b8bbe99 100644 --- a/packages/maskbook/src/extension/options-page/index.tsx +++ b/packages/maskbook/src/extension/options-page/index.tsx @@ -36,7 +36,6 @@ import { ErrorBoundary } from '../../components/shared/ErrorBoundary' import { MaskUIRoot } from '../../UIRoot' import { createInjectHooksRenderer, startPluginDashboard, useActivatedPluginsDashboard } from '@masknet/plugin-infra' import { createPluginHost } from '../../plugin-infra/host' -import { DashboardNFTAvatarsRouter } from './DashboardRouters/NFTAvatarList' const useStyles = makeStyles()((theme) => { const dark = theme.palette.mode === 'dark' @@ -195,7 +194,6 @@ function DashboardUI() { - {{userId}}? This operation cannot be reverted." + "profile_nft_avatar_set": "Set NFT Avatar" } diff --git a/packages/maskbook/src/locales/qya-AA.json b/packages/maskbook/src/locales/qya-AA.json index 6166637b5426..90b508a39444 100644 --- a/packages/maskbook/src/locales/qya-AA.json +++ b/packages/maskbook/src/locales/qya-AA.json @@ -248,8 +248,6 @@ "settings_post_replacement_desc": "crwdns4449:0crwdne4449:0", "settings_title_general": "crwdns4451:0crwdne4451:0", "settings_title_advanced_options": "crwdns4453:0crwdne4453:0", - "settings_title_bind_nft_avatar": "crwdns8185:0crwdne8185:0", - "bind_nft_avatar": "crwdns8187:0crwdne8187:0", "settings_title_database_management": "crwdns4455:0crwdne4455:0", "settings_launch_page": "crwdns4457:0crwdne4457:0", "settings_launch_page_secondary": "crwdns4459:0crwdne4459:0", @@ -905,7 +903,6 @@ "popups_wallet_unlock_error_password": "crwdns8075:0crwdne8075:0", "popups_missing_parameter_caption": "crwdns7827:0crwdne7827:0", "profile_nft_avatar_set": "crwdns8189:0crwdne8189:0", - "settings_nft_avatar_whitelist": "crwdns8197:0crwdne8197:0", "unbind_nft_avatar": "crwdns8199:0crwdne8199:0", "delete_nft_avatar": "crwdns8201:0{{userId}}crwdne8201:0" } From 60e283174953822c42ffa626a35d1c2e37dbc45f Mon Sep 17 00:00:00 2001 From: lelenei <72531217+lelenei@users.noreply.github.com> Date: Tue, 28 Sep 2021 12:39:38 +0800 Subject: [PATCH 6/7] refactor: remove unuse code --- .../InjectedComponents/NFT/gun/gun.ts | 64 ------------------- 1 file changed, 64 deletions(-) delete mode 100644 packages/maskbook/src/components/InjectedComponents/NFT/gun/gun.ts diff --git a/packages/maskbook/src/components/InjectedComponents/NFT/gun/gun.ts b/packages/maskbook/src/components/InjectedComponents/NFT/gun/gun.ts deleted file mode 100644 index 6deaaa219731..000000000000 --- a/packages/maskbook/src/components/InjectedComponents/NFT/gun/gun.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { AvatarMetaDB, NFT_AVATAR_SERVER } from '../types' - -const NFTAvatarCache = new Map() -async function getAvatarGun() { - // TODO: do not call gun in SNS adaptor. - const { gun2 } = await import('../../../../network/gun/version.2') - return { gun2 } -} - -async function getNFTAvatar(userId: string) { - const avatar = NFTAvatarCache.get(userId) - if (!avatar) { - NFTAvatarCache.set( - userId, - await ( - await getAvatarGun() - ).gun2 - .get(NFT_AVATAR_SERVER) - // @ts-expect-error - .get(userId).then!(), - ) - } - - return NFTAvatarCache.get(userId) -} - -async function setOrClearAvatar(userId: string, avatar?: AvatarMetaDB) { - await ( - await getAvatarGun() - ).gun2 - .get(NFT_AVATAR_SERVER) - // @ts-expect-error - .get(userId) - // @ts-expect-error - .put(avatar ? avatar : null).then!() -} - -async function getNFTAvatars() { - const NFTAvatarNodes = - (await ( - await getAvatarGun() - ).gun2 //@ts-expect-error - .get(NFT_AVATAR_SERVER).then!()) || [] - console.log(NFTAvatarNodes) - - const NFTAvatarKeys = Object.keys(NFTAvatarNodes).filter((x) => x !== '_') - const resultPromise = NFTAvatarKeys.map((key) => getNFTAvatar(key)) - const result = (await Promise.all(resultPromise)).filter((x) => x) as AvatarMetaDB[] - return result -} - -async function saveNFTAvatar(userId: string, avatarId: string, address: string, tokenId: string) { - const avatarMeta: AvatarMetaDB = { - userId, - address, - tokenId, - avatarId, - } - - await setOrClearAvatar(userId) - - await setOrClearAvatar(userId, avatarMeta) - return avatarMeta -} From 143f1e54554cf9d0bcf448897ea87ab7353df9bb Mon Sep 17 00:00:00 2001 From: lelenei <72531217+lelenei@users.noreply.github.com> Date: Wed, 29 Sep 2021 14:34:16 +0800 Subject: [PATCH 7/7] refactor: remove unuse code --- .../InjectedComponents/NFT/NFTAvatar.tsx | 1 - .../InjectedComponents/NFT/gun/db.ts | 62 ------------------- .../InjectedComponents/NFT/gun/index.ts | 53 +++++++++++++++- .../InjectedComponents/NFT/hooks/index.ts | 1 - .../NFT/hooks/useNFTAvatars.ts | 9 --- 5 files changed, 52 insertions(+), 74 deletions(-) delete mode 100644 packages/maskbook/src/components/InjectedComponents/NFT/gun/db.ts delete mode 100644 packages/maskbook/src/components/InjectedComponents/NFT/hooks/useNFTAvatars.ts diff --git a/packages/maskbook/src/components/InjectedComponents/NFT/NFTAvatar.tsx b/packages/maskbook/src/components/InjectedComponents/NFT/NFTAvatar.tsx index 3e29ba7ca08c..bda3ae862f4b 100644 --- a/packages/maskbook/src/components/InjectedComponents/NFT/NFTAvatar.tsx +++ b/packages/maskbook/src/components/InjectedComponents/NFT/NFTAvatar.tsx @@ -89,7 +89,6 @@ export function NFTAvatar(props: NFTAvatarProps) { retry, error, } = useCollectibles(account, chainId, provider, page, 50) - //0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045 const { collectibles, hasNextPage } = value diff --git a/packages/maskbook/src/components/InjectedComponents/NFT/gun/db.ts b/packages/maskbook/src/components/InjectedComponents/NFT/gun/db.ts deleted file mode 100644 index 7ee2f28e8e30..000000000000 --- a/packages/maskbook/src/components/InjectedComponents/NFT/gun/db.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { delay } from '@masknet/shared-base' -import { AvatarMetaDB, NFT_AVATAR_JSON_SERVER } from '../types' - -const EXPIRED_TIME = 5 * 60 * 1000 -const cache = new Map<'avatar', [number, Promise]>() - -async function fetchData() { - const response = await fetch(NFT_AVATAR_JSON_SERVER) - if (!response.ok) return [] - const json = (await response.json()) as AvatarMetaDB[] - return json -} - -async function _fetch() { - const c = cache.get('avatar') - let f, json - if (c) { - f = c[1] - if (!f) { - f = fetchData() - cache.set('avatar', [Date.now(), f]) - } - if (Date.now() - c[0] >= EXPIRED_TIME) { - json = await f - f = fetchData() - cache.set('avatar', [Date.now(), f]) - return json - } - } else { - f = fetchData() - cache.set('avatar', [Date.now(), f]) - } - - json = await f - return json -} - -export async function getNFTAvatar(userId: string) { - const db = (await _fetch()).filter((x) => x.userId === userId) - if (db?.length === 0) return - - return db[0] -} - -export async function setOrClearAvatar(userId: string, avatar?: AvatarMetaDB) { - await delay(500) -} - -export async function getNFTAvatars() { - const AvatarDB = await _fetch() - return AvatarDB -} - -export async function saveNFTAvatar(userId: string, avatarId: string, address: string, tokenId: string) { - await delay(500) - return { - userId, - avatarId, - address, - tokenId, - } -} diff --git a/packages/maskbook/src/components/InjectedComponents/NFT/gun/index.ts b/packages/maskbook/src/components/InjectedComponents/NFT/gun/index.ts index 1beb455f5e39..10f4e541b362 100644 --- a/packages/maskbook/src/components/InjectedComponents/NFT/gun/index.ts +++ b/packages/maskbook/src/components/InjectedComponents/NFT/gun/index.ts @@ -1 +1,52 @@ -export * from './db' +import { delay } from '@masknet/shared-base' +import { first } from 'lodash-es' +import { AvatarMetaDB, NFT_AVATAR_JSON_SERVER } from '../types' + +const EXPIRED_TIME = 5 * 60 * 1000 +const cache = new Map<'avatar', [number, Promise]>() + +async function fetchData() { + const response = await fetch(NFT_AVATAR_JSON_SERVER) + if (!response.ok) return [] + const json = (await response.json()) as AvatarMetaDB[] + return json +} + +async function _fetch() { + const c = cache.get('avatar') + let f, json + if (c) { + f = c[1] + if (!f) { + f = fetchData() + cache.set('avatar', [Date.now(), f]) + } + if (Date.now() - c[0] >= EXPIRED_TIME) { + json = await f + f = fetchData() + cache.set('avatar', [Date.now(), f]) + return json + } + } else { + f = fetchData() + cache.set('avatar', [Date.now(), f]) + } + + json = await f + return json +} + +export async function getNFTAvatar(userId: string) { + const db = (await _fetch()).filter((x) => x.userId === userId) + return first(db) +} + +export async function saveNFTAvatar(userId: string, avatarId: string, address: string, tokenId: string) { + await delay(500) + return { + userId, + avatarId, + address, + tokenId, + } +} diff --git a/packages/maskbook/src/components/InjectedComponents/NFT/hooks/index.ts b/packages/maskbook/src/components/InjectedComponents/NFT/hooks/index.ts index 36180066ff21..56bdf8e663c2 100644 --- a/packages/maskbook/src/components/InjectedComponents/NFT/hooks/index.ts +++ b/packages/maskbook/src/components/InjectedComponents/NFT/hooks/index.ts @@ -1,3 +1,2 @@ export * from './useNFT' export * from './useNFTAvatar' -export * from './useNFTAvatars' diff --git a/packages/maskbook/src/components/InjectedComponents/NFT/hooks/useNFTAvatars.ts b/packages/maskbook/src/components/InjectedComponents/NFT/hooks/useNFTAvatars.ts deleted file mode 100644 index 4c8e39d235b8..000000000000 --- a/packages/maskbook/src/components/InjectedComponents/NFT/hooks/useNFTAvatars.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { useAsyncRetry } from 'react-use' -import { getNFTAvatars } from '../gun' - -export function useNFTAvatars() { - return useAsyncRetry(async () => { - const result = await getNFTAvatars() - return result - }, [getNFTAvatars]) -}