From 7905759bc16b714f00e32d9986438dd19089f8f8 Mon Sep 17 00:00:00 2001 From: nuanyang233 <528944303@qq.com> Date: Wed, 22 Dec 2021 11:04:18 +0800 Subject: [PATCH 1/3] refactor: profile nft avatar (#5248) * refactor: profile nft avatar * fix: shadow style * chore: reply review (cherry picked from commit 5c36ce586ecae196994c70284378db3c199a9012) --- .../Avatar/SNSAdaptor/NFTAvatarRing.tsx | 72 +++++++++++------ .../plugins/Avatar/SNSAdaptor/RainbowBox.tsx | 58 +++++++------- .../injection/NFT/NFTAvatarInTwitter.tsx | 77 +++++-------------- .../twitter.com/utils/selector.ts | 9 +-- 4 files changed, 101 insertions(+), 115 deletions(-) diff --git a/packages/mask/src/plugins/Avatar/SNSAdaptor/NFTAvatarRing.tsx b/packages/mask/src/plugins/Avatar/SNSAdaptor/NFTAvatarRing.tsx index 135aac2d5b2a..360faf38bc08 100644 --- a/packages/mask/src/plugins/Avatar/SNSAdaptor/NFTAvatarRing.tsx +++ b/packages/mask/src/plugins/Avatar/SNSAdaptor/NFTAvatarRing.tsx @@ -1,5 +1,7 @@ import { makeStyles } from '@masknet/theme' -import { RainbowBox } from './RainbowBox' +import { rainbowBorderKeyFrames, RainbowBox } from './RainbowBox' +import { useMount } from 'react-use' +import { searchTwitterAvatarLinkSelector } from '../../../social-network-adaptor/twitter.com/utils/selector' const useStyles = makeStyles()((theme) => ({ root: { @@ -20,24 +22,57 @@ export function NFTAvatarRing(props: NFTAvatarRingProps) { const { stroke, strokeWidth, fontSize, text, width, id } = props const avatarSize = width + 3 - const R = width + 2 * strokeWidth - 4 - const r = R / 2 - strokeWidth - const path_r = R / 2 - strokeWidth + fontSize / 2 - const x1 = R / 2 - path_r / 2 - const y1 = R / 2 + Math.sqrt(Math.pow(path_r, 2) - Math.pow(path_r / 2, 2)) - const x2 = R / 2 + path_r / 2 - const y2 = y1 + const R = avatarSize / 2 + const path_r = R - strokeWidth + fontSize / 2 + const x1 = R - path_r / 2 + const y1 = R + Math.sqrt(Math.pow(path_r, 2) - Math.pow(path_r / 2, 2)) + const x2 = R + path_r / 2 + + useMount(() => { + const linkDom = searchTwitterAvatarLinkSelector().evaluate() + + if (linkDom?.firstElementChild && linkDom.childNodes.length === 4) { + const linkParentDom = linkDom.closest('div') + + if (linkParentDom) linkParentDom.style.overflow = 'visible' + + // remove useless border + linkDom.removeChild(linkDom.firstElementChild) + + // create rainbow shadow border + if (linkDom.firstElementChild.tagName !== 'style') { + const style = document.createElement('style') + style.innerText = ` + ${rainbowBorderKeyFrames.styles} + + .rainbowBorder { + animation: ${rainbowBorderKeyFrames.name} 6s linear infinite; + box-shadow: 0 5px 15px rgba(0, 248, 255, 0.4), 0 10px 30px rgba(37, 41, 46, 0.2); + transition: .125s ease; + border: 2px solid #00f8ff; + } + ` + linkDom.firstElementChild.classList.add('rainbowBorder') + linkDom.insertBefore(style, linkDom.firstChild) + } + } + }) return ( - - + + @@ -49,23 +84,16 @@ export function NFTAvatarRing(props: NFTAvatarRingProps) { - + - + diff --git a/packages/mask/src/plugins/Avatar/SNSAdaptor/RainbowBox.tsx b/packages/mask/src/plugins/Avatar/SNSAdaptor/RainbowBox.tsx index 4b6a18089f03..25c39d6cd47d 100644 --- a/packages/mask/src/plugins/Avatar/SNSAdaptor/RainbowBox.tsx +++ b/packages/mask/src/plugins/Avatar/SNSAdaptor/RainbowBox.tsx @@ -1,35 +1,33 @@ import { keyframes, makeStyles, useStylesExtends } from '@masknet/theme' +import type { Keyframes } from '@emotion/serialize' -const rainbowBorderKeyFrames = keyframes` -0%,to { - border-color: #00f8ff; - box-shadow: 0 5px 15px rgba(0,248,255,.4),0 10px 30px rgba(37,41,46,.2); -} - -20% { - border-color: #a4ff00; - box-shadow: 0 5px 15px rgba(164,255,0,.4),0 10px 30px rgba(37,41,46,.2); -} - -40% { - border-color: #f7275e; - box-shadow: 0 5px 15px rgba(247,39,94,.4),0 10px 30px rgba(37,41,46,.2) -} - -60% { - border-color: #ffd300; - box-shadow: 0 5px 15px rgba(255,211,0,.4),0 10px 30px rgba(37,41,46,.2) -} - -80% { - border-color: #ff8a00; - box-shadow: 0 5px 15px rgba(255,138,0,.4),0 10px 30px rgba(37,41,46,.2) -} +export const rainbowBorderKeyFrames: Keyframes = keyframes` + 0%, + to { + border-color: #00f8ff; + box-shadow: 0 5px 15px rgba(0, 248, 255, 0.4), 0 10px 30px rgba(37, 41, 46, 0.2); + } + 20% { + border-color: #a4ff00; + box-shadow: 0 5px 15px rgba(164, 255, 0, 0.4), 0 10px 30px rgba(37, 41, 46, 0.2); + } + 40% { + border-color: #f7275e; + box-shadow: 0 5px 15px rgba(247, 39, 94, 0.4), 0 10px 30px rgba(37, 41, 46, 0.2); + } + 60% { + border-color: #ffd300; + box-shadow: 0 5px 15px rgba(255, 211, 0, 0.4), 0 10px 30px rgba(37, 41, 46, 0.2); + } + 80% { + border-color: #ff8a00; + box-shadow: 0 5px 15px rgba(255, 138, 0, 0.4), 0 10px 30px rgba(37, 41, 46, 0.2); + } ` interface StyleProps { - width: number - height: number + width?: number + height?: number radius?: string } const useStyles = makeStyles()((theme, { width, height, radius = '100%' }) => ({ @@ -37,7 +35,7 @@ const useStyles = makeStyles()((theme, { width, height, radius = '10 animation: `${rainbowBorderKeyFrames} 6s linear infinite`, width, height, - boxShadow: 'box-shadow: 0 5px 15px rgb(0 248 255 / 40%), 0 10px 30px rgb(37 41 46 / 20%);', + boxShadow: '0 5px 15px rgba(0, 248, 255, 0.4), 0 10px 30px rgba(37, 41, 46, 0.2)', transition: '.125s ease', borderRadius: radius, display: 'flex', @@ -49,8 +47,8 @@ const useStyles = makeStyles()((theme, { width, height, radius = '10 })) interface RainbowBoxProps extends withClasses<'root'> { - width: number - height: number + width?: number + height?: number radius?: string children?: React.ReactNode } diff --git a/packages/mask/src/social-network-adaptor/twitter.com/injection/NFT/NFTAvatarInTwitter.tsx b/packages/mask/src/social-network-adaptor/twitter.com/injection/NFT/NFTAvatarInTwitter.tsx index 404bd4a2f186..e76385eadcd3 100644 --- a/packages/mask/src/social-network-adaptor/twitter.com/injection/NFT/NFTAvatarInTwitter.tsx +++ b/packages/mask/src/social-network-adaptor/twitter.com/injection/NFT/NFTAvatarInTwitter.tsx @@ -1,8 +1,8 @@ import { createReactRootShadowed, MaskMessages, NFTAvatarEvent, startWatch } from '../../../../utils' -import { searchTwitterAvatarLinkSelector, searchTwitterAvatarSelector } from '../../utils/selector' +import { searchTwitterAvatarSelector } from '../../utils/selector' import { MutationObserverWatcher } from '@dimensiondev/holoflows-kit' import { makeStyles } from '@masknet/theme' -import { useState, useEffect } from 'react' +import { useState, useEffect, useMemo } from 'react' import { useCurrentVisitingIdentity } from '../../../../components/DataSource/useActivatedUI' import { useWallet } from '@masknet/web3-shared-evm' @@ -12,45 +12,22 @@ import { getAvatarId } from '../../utils/user' import { PluginNFTAvatarRPC } from '../../../../plugins/Avatar/messages' import { NFTBadge } from '../../../../plugins/Avatar/SNSAdaptor/NFTBadge' import { NFTAvatar } from '../../../../plugins/Avatar/SNSAdaptor/NFTAvatar' +import { useWindowSize } from 'react-use' -const offset = 10 export function injectNFTAvatarInTwitter(signal: AbortSignal) { const watcher = new MutationObserverWatcher(searchTwitterAvatarSelector()) startWatch(watcher, signal) createReactRootShadowed(watcher.firstDOMProxy.afterShadow, { signal }).render() } -interface StyleProps { - width: number - size: number -} - -const useStyles = makeStyles()((theme, props) => ({ +const useStyles = makeStyles()(() => ({ root: { position: 'absolute', - bottom: '-10px !important', textAlign: 'center', color: 'white', - minWidth: 134, zIndex: 2, - - left: -1 * props.width + offset / 2, - top: -1 * props.width + offset / 2, - width: props.size, - height: props.size, - - [`@media (max-width: ${theme.breakpoints.values.sm}px)`]: { - left: -27, - top: -1 * props.width, - }, - }, - update: { - position: 'absolute', - bottom: '-10px !important', - left: 55, - textAlign: 'center', - color: 'white', - minWidth: 134, + width: '100%', + height: '100%', }, text: { fontSize: '20px !important', @@ -67,14 +44,19 @@ function NFTAvatarInTwitter() { const wallet = useWallet() const { value: _avatar } = useNFTAvatar(identity.identifier.userId) const [avatar, setAvatar] = useState() - const ele = searchTwitterAvatarLinkSelector().evaluate() - let size = 170 - const width = 15 - if (ele) { - const style = window.getComputedStyle(ele) - size = Number(style.width.replace('px', '') ?? 0) - Number(style.borderWidth.replace('px', '') ?? 0) - offset - } - const { classes } = useStyles({ size: size + width * 2, width }) + + const windowSize = useWindowSize() + + const size = useMemo(() => { + const ele = searchTwitterAvatarSelector().evaluate() + if (ele) { + const style = window.getComputedStyle(ele) + return Number.parseInt(style.width.replace('px', '') ?? 0, 10) + } + return 0 + }, [windowSize]) + + const { classes } = useStyles() const [NFTEvent, setNFTEvent] = useState() const onUpdate = (data: NFTAvatarEvent) => { @@ -120,26 +102,7 @@ function NFTAvatarInTwitter() { return MaskMessages.events.NFTAvatarUpdated.on((data) => onUpdate(data)) }, [onUpdate]) - useEffect(() => { - if (!avatar || !avatar.avatarId) return - if (getAvatarId(identity.avatar ?? '') !== avatar.avatarId) return - const avatarDom = searchTwitterAvatarSelector().evaluate()?.parentElement - if (avatarDom) { - avatarDom.style.marginBottom = '10px' - avatarDom.style.overflow = 'unset' - } - - const backgroundImgDom = searchTwitterAvatarSelector().evaluate()?.firstChild?.nextSibling?.firstChild - ?.firstChild as HTMLElement - if (backgroundImgDom) { - backgroundImgDom.style.borderRadius = '100%' - } - }, [identity, avatar, searchTwitterAvatarSelector, searchTwitterAvatarSelector]) - - if (!avatar) return null - - const avatarParent = searchTwitterAvatarSelector().closest(2).evaluate() as HTMLElement - if (avatarParent) avatarParent.style.clipPath = 'unset' + if (!avatar || !size) return null return ( <> diff --git a/packages/mask/src/social-network-adaptor/twitter.com/utils/selector.ts b/packages/mask/src/social-network-adaptor/twitter.com/utils/selector.ts index 36fd4d9b525a..f8305af1cd78 100644 --- a/packages/mask/src/social-network-adaptor/twitter.com/utils/selector.ts +++ b/packages/mask/src/social-network-adaptor/twitter.com/utils/selector.ts @@ -50,7 +50,7 @@ export const searchProfileTabListSelector = () => export const searchForegroundColorSelector: () => LiveSelector = () => querySelector('[data-testid="primaryColumn"] > div > div > div > div > div > div > div > div > div > div') export const searchNewTweetButtonSelector: () => LiveSelector = () => { - const q = querySelector('[data-testid="FloatingActionButtons_Tweet_Button"') + const q = querySelector('[data-testid="FloatingActionButtons_Tweet_Button"]') if (q.evaluate()) return q return querySelector('[data-testid="SideNav_NewTweet_Button"]') } @@ -227,17 +227,14 @@ export const searchProfessionalButtonSelector = () => //#endregion //#region avatar selector - export const searchTwitterAvatarLinkSelector: () => LiveSelector = () => querySelector('[data-testid="UserProfileHeader_Items"]').closest(2).querySelector('div a') -export const searchTwitterAvatarSelector = () => searchTwitterAvatarLinkSelector().querySelector('div') +export const searchTwitterAvatarSelector = () => + querySelector('[data-testid="UserProfileHeader_Items"]').closest(2).querySelector('img').closest(1) //#endregion //#region twitter avatar -export const searchAccountSwitherButtonSelector = () => - querySelector('[data-testid="SideNav_AccountSwitcher_Button"]') - export const searchUseCellSelector = () => querySelector('[data-testid="UserCell"]') //#endregion From 905bc4d0df698ff5f74613dfee440022dc1d7d92 Mon Sep 17 00:00:00 2001 From: nuanyang233 Date: Mon, 27 Dec 2021 22:41:46 +0800 Subject: [PATCH 2/3] fix: hidden rainbow when nft avatar isn't exist (#5320) (cherry picked from commit 2920d498d5b660d86967292872a5ea883882367f) --- .../Avatar/SNSAdaptor/NFTAvatarRing.tsx | 34 +------------- .../injection/NFT/NFTAvatarInTwitter.tsx | 47 +++++++++++++++++-- 2 files changed, 45 insertions(+), 36 deletions(-) diff --git a/packages/mask/src/plugins/Avatar/SNSAdaptor/NFTAvatarRing.tsx b/packages/mask/src/plugins/Avatar/SNSAdaptor/NFTAvatarRing.tsx index 360faf38bc08..bd20c64ce021 100644 --- a/packages/mask/src/plugins/Avatar/SNSAdaptor/NFTAvatarRing.tsx +++ b/packages/mask/src/plugins/Avatar/SNSAdaptor/NFTAvatarRing.tsx @@ -1,7 +1,5 @@ import { makeStyles } from '@masknet/theme' -import { rainbowBorderKeyFrames, RainbowBox } from './RainbowBox' -import { useMount } from 'react-use' -import { searchTwitterAvatarLinkSelector } from '../../../social-network-adaptor/twitter.com/utils/selector' +import { RainbowBox } from './RainbowBox' const useStyles = makeStyles()((theme) => ({ root: { @@ -28,36 +26,6 @@ export function NFTAvatarRing(props: NFTAvatarRingProps) { const y1 = R + Math.sqrt(Math.pow(path_r, 2) - Math.pow(path_r / 2, 2)) const x2 = R + path_r / 2 - useMount(() => { - const linkDom = searchTwitterAvatarLinkSelector().evaluate() - - if (linkDom?.firstElementChild && linkDom.childNodes.length === 4) { - const linkParentDom = linkDom.closest('div') - - if (linkParentDom) linkParentDom.style.overflow = 'visible' - - // remove useless border - linkDom.removeChild(linkDom.firstElementChild) - - // create rainbow shadow border - if (linkDom.firstElementChild.tagName !== 'style') { - const style = document.createElement('style') - style.innerText = ` - ${rainbowBorderKeyFrames.styles} - - .rainbowBorder { - animation: ${rainbowBorderKeyFrames.name} 6s linear infinite; - box-shadow: 0 5px 15px rgba(0, 248, 255, 0.4), 0 10px 30px rgba(37, 41, 46, 0.2); - transition: .125s ease; - border: 2px solid #00f8ff; - } - ` - linkDom.firstElementChild.classList.add('rainbowBorder') - linkDom.insertBefore(style, linkDom.firstChild) - } - } - }) - return ( ({ })) function NFTAvatarInTwitter() { + const rainBowElement = useRef() const identity = useCurrentVisitingIdentity() const wallet = useWallet() const { value: _avatar } = useNFTAvatar(identity.identifier.userId) @@ -102,6 +104,45 @@ function NFTAvatarInTwitter() { return MaskMessages.events.NFTAvatarUpdated.on((data) => onUpdate(data)) }, [onUpdate]) + useMount(() => { + const linkDom = searchTwitterAvatarLinkSelector().evaluate() + + if (linkDom?.firstElementChild && linkDom.childNodes.length === 4) { + const linkParentDom = linkDom.closest('div') + + if (linkParentDom) linkParentDom.style.overflow = 'visible' + + // remove useless border + linkDom.removeChild(linkDom.firstElementChild) + + // create rainbow shadow border + if (linkDom.firstElementChild.tagName !== 'style') { + const style = document.createElement('style') + style.innerText = ` + ${rainbowBorderKeyFrames.styles} + + .rainbowBorder { + animation: ${rainbowBorderKeyFrames.name} 6s linear infinite; + box-shadow: 0 5px 15px rgba(0, 248, 255, 0.4), 0 10px 30px rgba(37, 41, 46, 0.2); + transition: .125s ease; + border: 2px solid #00f8ff; + } + ` + rainBowElement.current = linkDom.firstElementChild + linkDom.firstElementChild.classList.add('rainbowBorder') + linkDom.insertBefore(style, linkDom.firstChild) + } + } + }) + + useUpdateEffect(() => { + if (!avatar) { + rainBowElement.current?.classList.remove('rainbowBorder') + } else { + rainBowElement.current?.classList.add('rainbowBorder') + } + }, [avatar]) + if (!avatar || !size) return null return ( From 68d3a7d9116d5d06571b4d257eb5004928a29acb Mon Sep 17 00:00:00 2001 From: nuanyang233 Date: Wed, 29 Dec 2021 17:17:15 +0800 Subject: [PATCH 3/3] fix: recovery normal style when user doesn't have an NFT avatar (#5329) * fix: recovery normal style when user doesn't have an NFT avatar * fix: bugfix * fix: open opensea link when user click nft avatar * chore: reply review (cherry picked from commit 45e12e534ccb7f125de5d39bf41a5192d9de70e1) --- .../injection/NFT/NFTAvatarInTwitter.tsx | 104 +++++++++++++----- 1 file changed, 74 insertions(+), 30 deletions(-) diff --git a/packages/mask/src/social-network-adaptor/twitter.com/injection/NFT/NFTAvatarInTwitter.tsx b/packages/mask/src/social-network-adaptor/twitter.com/injection/NFT/NFTAvatarInTwitter.tsx index b47839b2006f..e56fed2ab7a4 100644 --- a/packages/mask/src/social-network-adaptor/twitter.com/injection/NFT/NFTAvatarInTwitter.tsx +++ b/packages/mask/src/social-network-adaptor/twitter.com/injection/NFT/NFTAvatarInTwitter.tsx @@ -3,17 +3,17 @@ import { searchTwitterAvatarLinkSelector, searchTwitterAvatarSelector } from '.. import { MutationObserverWatcher } from '@dimensiondev/holoflows-kit' import { makeStyles } from '@masknet/theme' import { useState, useEffect, useMemo, useRef } from 'react' - import { useCurrentVisitingIdentity } from '../../../../components/DataSource/useActivatedUI' -import { useWallet } from '@masknet/web3-shared-evm' +import { resolveOpenSeaLink, useWallet } from '@masknet/web3-shared-evm' import type { AvatarMetaDB } from '../../../../plugins/Avatar/types' import { useNFTAvatar } from '../../../../plugins/Avatar/hooks' import { getAvatarId } from '../../utils/user' import { PluginNFTAvatarRPC } from '../../../../plugins/Avatar/messages' import { NFTBadge } from '../../../../plugins/Avatar/SNSAdaptor/NFTBadge' import { NFTAvatar } from '../../../../plugins/Avatar/SNSAdaptor/NFTAvatar' -import { useMount, useUpdateEffect, useWindowSize } from 'react-use' +import { useAsync, useLocation, useUpdateEffect, useWindowSize } from 'react-use' import { rainbowBorderKeyFrames } from '../../../../plugins/Avatar/SNSAdaptor/RainbowBox' +import { trim } from 'lodash-unified' export function injectNFTAvatarInTwitter(signal: AbortSignal) { const watcher = new MutationObserverWatcher(searchTwitterAvatarSelector()) @@ -42,12 +42,18 @@ const useStyles = makeStyles()(() => ({ function NFTAvatarInTwitter() { const rainBowElement = useRef() + const borderElement = useRef() const identity = useCurrentVisitingIdentity() const wallet = useWallet() const { value: _avatar } = useNFTAvatar(identity.identifier.userId) const [avatar, setAvatar] = useState() - const windowSize = useWindowSize() + const location = useLocation() + + const showAvatar = useMemo( + () => getAvatarId(identity.avatar ?? '') === avatar?.avatarId && avatar.avatarId, + [avatar?.avatarId, identity.avatar], + ) const size = useMemo(() => { const ele = searchTwitterAvatarSelector().evaluate() @@ -65,7 +71,7 @@ function NFTAvatarInTwitter() { setNFTEvent(data) } - useEffect(() => { + useAsync(async () => { if (!wallet || !NFTAvatar) return if (!NFTEvent?.address || !NFTEvent?.tokenId) { @@ -79,20 +85,21 @@ function NFTAvatarInTwitter() { return } - PluginNFTAvatarRPC.saveNFTAvatar(wallet.address, { + const avatar = await PluginNFTAvatarRPC.saveNFTAvatar(wallet.address, { ...NFTEvent, avatarId: getAvatarId(identity.avatar ?? ''), - } as AvatarMetaDB).then((avatar: AvatarMetaDB | undefined) => { - setAvatar(avatar) - MaskMessages.events.NFTAvatarTimelineUpdated.sendToAll( - avatar ?? { - userId: identity.identifier.userId, - avatarId: getAvatarId(identity.avatar ?? ''), - address: '', - tokenId: '', - }, - ) - }) + } as AvatarMetaDB) + + setAvatar(avatar) + MaskMessages.events.NFTAvatarTimelineUpdated.sendToAll( + avatar ?? { + userId: identity.identifier.userId, + avatarId: getAvatarId(identity.avatar ?? ''), + address: '', + tokenId: '', + }, + ) + setNFTEvent(undefined) }, [identity.avatar]) @@ -104,7 +111,7 @@ function NFTAvatarInTwitter() { return MaskMessages.events.NFTAvatarUpdated.on((data) => onUpdate(data)) }, [onUpdate]) - useMount(() => { + useEffect(() => { const linkDom = searchTwitterAvatarLinkSelector().evaluate() if (linkDom?.firstElementChild && linkDom.childNodes.length === 4) { @@ -112,11 +119,12 @@ function NFTAvatarInTwitter() { if (linkParentDom) linkParentDom.style.overflow = 'visible' - // remove useless border - linkDom.removeChild(linkDom.firstElementChild) - // create rainbow shadow border - if (linkDom.firstElementChild.tagName !== 'style') { + if (linkDom.lastElementChild?.tagName !== 'STYLE') { + borderElement.current = linkDom.firstElementChild + + // remove useless border + linkDom.removeChild(linkDom.firstElementChild) const style = document.createElement('style') style.innerText = ` ${rainbowBorderKeyFrames.styles} @@ -129,17 +137,53 @@ function NFTAvatarInTwitter() { } ` rainBowElement.current = linkDom.firstElementChild - linkDom.firstElementChild.classList.add('rainbowBorder') - linkDom.insertBefore(style, linkDom.firstChild) + if (showAvatar) linkDom.firstElementChild.classList.add('rainbowBorder') + linkDom.appendChild(style) } } - }) + }, [location.pathname]) + + useEffect(() => { + const linkDom = searchTwitterAvatarLinkSelector().evaluate() + if (showAvatar) { + if (borderElement.current && linkDom?.firstElementChild === borderElement.current) { + linkDom?.removeChild(linkDom.firstElementChild) + } - useUpdateEffect(() => { - if (!avatar) { - rainBowElement.current?.classList.remove('rainbowBorder') - } else { rainBowElement.current?.classList.add('rainbowBorder') + } else { + // recovery Twitter profile avatar style + if (borderElement.current && linkDom?.firstElementChild !== borderElement.current) { + linkDom?.insertBefore(borderElement.current, linkDom.firstChild) + } + + rainBowElement.current?.classList.remove('rainbowBorder') + } + }, [showAvatar]) + + useUpdateEffect(() => { + if ( + location.pathname && + location.pathname.split('/').length === 2 && + trim(location.pathname, '/') !== identity.identifier.userId + ) { + setAvatar(undefined) + } + }, [location, identity]) + + useUpdateEffect(() => { + const linkParentDom = searchTwitterAvatarLinkSelector().evaluate()?.closest('div') + + if (!avatar || !linkParentDom) return + + const handler = () => { + window.open(resolveOpenSeaLink(avatar.address, avatar.tokenId), '_blank') + } + + linkParentDom.addEventListener('click', handler) + + return () => { + linkParentDom.removeEventListener('click', handler) } }, [avatar]) @@ -147,7 +191,7 @@ function NFTAvatarInTwitter() { return ( <> - {getAvatarId(identity.avatar ?? '') === avatar.avatarId && avatar.avatarId ? ( + {showAvatar ? (