From 818eff9931e9f94715a69887f3188c4d500f09ae Mon Sep 17 00:00:00 2001 From: nuanyang233 <528944303@qq.com> Date: Tue, 21 Dec 2021 01:12:09 +0800 Subject: [PATCH 1/3] refactor: profile nft avatar --- .../Avatar/SNSAdaptor/NFTAvatarRing.tsx | 38 +++---- .../plugins/Avatar/SNSAdaptor/RainbowBox.tsx | 13 +-- .../injection/NFT/NFTAvatarInTwitter.tsx | 100 ++++++++---------- .../twitter.com/utils/selector.ts | 9 +- 4 files changed, 73 insertions(+), 87 deletions(-) diff --git a/packages/mask/src/plugins/Avatar/SNSAdaptor/NFTAvatarRing.tsx b/packages/mask/src/plugins/Avatar/SNSAdaptor/NFTAvatarRing.tsx index 135aac2d5b2a..bd20c64ce021 100644 --- a/packages/mask/src/plugins/Avatar/SNSAdaptor/NFTAvatarRing.tsx +++ b/packages/mask/src/plugins/Avatar/SNSAdaptor/NFTAvatarRing.tsx @@ -20,24 +20,27 @@ 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 return ( - - + + @@ -49,23 +52,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..5fffcb375aaf 100644 --- a/packages/mask/src/plugins/Avatar/SNSAdaptor/RainbowBox.tsx +++ b/packages/mask/src/plugins/Avatar/SNSAdaptor/RainbowBox.tsx @@ -1,6 +1,7 @@ import { keyframes, makeStyles, useStylesExtends } from '@masknet/theme' +import type { Keyframes } from '@emotion/serialize' -const rainbowBorderKeyFrames = keyframes` +export const rainbowBorderKeyFrames: Keyframes = keyframes` 0%,to { border-color: #00f8ff; box-shadow: 0 5px 15px rgba(0,248,255,.4),0 10px 30px rgba(37,41,46,.2); @@ -28,8 +29,8 @@ const rainbowBorderKeyFrames = keyframes` ` interface StyleProps { - width: number - height: number + width?: number + height?: number radius?: string } const useStyles = makeStyles()((theme, { width, height, radius = '100%' }) => ({ @@ -37,7 +38,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,.4),0 10px 30px rgba(37,41,46,.2)', transition: '.125s ease', borderRadius: radius, display: 'flex', @@ -49,8 +50,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..daad710d1c9e 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 @@ -2,7 +2,7 @@ import { createReactRootShadowed, MaskMessages, NFTAvatarEvent, startWatch } fro import { searchTwitterAvatarLinkSelector, 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,23 @@ 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, useWindowSize } from 'react-use' +import { rainbowBorderKeyFrames } from '../../../../plugins/Avatar/SNSAdaptor/RainbowBox' -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 +45,20 @@ 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(style.width.replace('px', '') ?? 0) + } + return 0 + }, [windowSize]) + + console.log(rainbowBorderKeyFrames) + const { classes } = useStyles() const [NFTEvent, setNFTEvent] = useState() const onUpdate = (data: NFTAvatarEvent) => { @@ -120,26 +104,34 @@ 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%' + useMount(() => { + const linkDom = searchTwitterAvatarLinkSelector().evaluate() + + if (linkDom?.firstElementChild && linkDom.childNodes.length === 4) { + // remove useless border + linkDom.removeChild(linkDom.firstElementChild) + + console.log(linkDom.firstElementChild.tagName) + // 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,.4),0 10px 30px rgba(37,41,46,.2); + transition: .125s ease; + border: 2px solid #00f8ff; + } + ` + linkDom.firstElementChild.classList.add('rainbowBorder') + linkDom.insertBefore(style, linkDom.firstChild) + } } - }, [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 ba73bedacd5c..08bae6fccaba 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"]') } @@ -225,17 +225,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 69820ebdade14842d4a9c0f941ba24f1680dc39b Mon Sep 17 00:00:00 2001 From: nuanyang233 <528944303@qq.com> Date: Tue, 21 Dec 2021 16:46:35 +0800 Subject: [PATCH 2/3] fix: shadow style --- .../Avatar/SNSAdaptor/NFTAvatarRing.tsx | 34 +++++++++++- .../plugins/Avatar/SNSAdaptor/RainbowBox.tsx | 52 ++++++++++--------- .../injection/NFT/NFTAvatarInTwitter.tsx | 33 +----------- 3 files changed, 62 insertions(+), 57 deletions(-) diff --git a/packages/mask/src/plugins/Avatar/SNSAdaptor/NFTAvatarRing.tsx b/packages/mask/src/plugins/Avatar/SNSAdaptor/NFTAvatarRing.tsx index bd20c64ce021..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: { @@ -26,6 +28,36 @@ 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 ( ()((theme, { width, height, radius = '10 animation: `${rainbowBorderKeyFrames} 6s linear infinite`, width, height, - boxShadow: '0 5px 15px rgba(0,248,255,.4),0 10px 30px rgba(37,41,46,.2)', + 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', 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 daad710d1c9e..6dbd23fa133b 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,5 +1,5 @@ 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, useMemo } from 'react' @@ -12,8 +12,7 @@ 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, useWindowSize } from 'react-use' -import { rainbowBorderKeyFrames } from '../../../../plugins/Avatar/SNSAdaptor/RainbowBox' +import { useWindowSize } from 'react-use' export function injectNFTAvatarInTwitter(signal: AbortSignal) { const watcher = new MutationObserverWatcher(searchTwitterAvatarSelector()) @@ -57,7 +56,6 @@ function NFTAvatarInTwitter() { return 0 }, [windowSize]) - console.log(rainbowBorderKeyFrames) const { classes } = useStyles() const [NFTEvent, setNFTEvent] = useState() @@ -104,33 +102,6 @@ function NFTAvatarInTwitter() { return MaskMessages.events.NFTAvatarUpdated.on((data) => onUpdate(data)) }, [onUpdate]) - useMount(() => { - const linkDom = searchTwitterAvatarLinkSelector().evaluate() - - if (linkDom?.firstElementChild && linkDom.childNodes.length === 4) { - // remove useless border - linkDom.removeChild(linkDom.firstElementChild) - - console.log(linkDom.firstElementChild.tagName) - // 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,.4),0 10px 30px rgba(37,41,46,.2); - transition: .125s ease; - border: 2px solid #00f8ff; - } - ` - linkDom.firstElementChild.classList.add('rainbowBorder') - linkDom.insertBefore(style, linkDom.firstChild) - } - } - }) - if (!avatar || !size) return null return ( From 27d2a4cf2d444cca2f3d117e3e40393523bc2f6c Mon Sep 17 00:00:00 2001 From: nuanyang233 <528944303@qq.com> Date: Tue, 21 Dec 2021 20:17:09 +0800 Subject: [PATCH 3/3] chore: reply review --- packages/mask/src/plugins/Avatar/SNSAdaptor/RainbowBox.tsx | 5 ----- .../twitter.com/injection/NFT/NFTAvatarInTwitter.tsx | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/packages/mask/src/plugins/Avatar/SNSAdaptor/RainbowBox.tsx b/packages/mask/src/plugins/Avatar/SNSAdaptor/RainbowBox.tsx index fa9be3071331..25c39d6cd47d 100644 --- a/packages/mask/src/plugins/Avatar/SNSAdaptor/RainbowBox.tsx +++ b/packages/mask/src/plugins/Avatar/SNSAdaptor/RainbowBox.tsx @@ -5,27 +5,22 @@ export const rainbowBorderKeyFrames: Keyframes = keyframes` 0%, to { border-color: #00f8ff; - -webkit-box-shadow: 0 5px 15px rgba(0, 248, 255, 0.4), 0 10px 30px rgba(37, 41, 46, 0.2); box-shadow: 0 5px 15px rgba(0, 248, 255, 0.4), 0 10px 30px rgba(37, 41, 46, 0.2); } 20% { border-color: #a4ff00; - -webkit-box-shadow: 0 5px 15px rgba(164, 255, 0, 0.4), 0 10px 30px rgba(37, 41, 46, 0.2); box-shadow: 0 5px 15px rgba(164, 255, 0, 0.4), 0 10px 30px rgba(37, 41, 46, 0.2); } 40% { border-color: #f7275e; - -webkit-box-shadow: 0 5px 15px rgba(247, 39, 94, 0.4), 0 10px 30px rgba(37, 41, 46, 0.2); box-shadow: 0 5px 15px rgba(247, 39, 94, 0.4), 0 10px 30px rgba(37, 41, 46, 0.2); } 60% { border-color: #ffd300; - -webkit-box-shadow: 0 5px 15px rgba(255, 211, 0, 0.4), 0 10px 30px rgba(37, 41, 46, 0.2); box-shadow: 0 5px 15px rgba(255, 211, 0, 0.4), 0 10px 30px rgba(37, 41, 46, 0.2); } 80% { border-color: #ff8a00; - -webkit-box-shadow: 0 5px 15px rgba(255, 138, 0, 0.4), 0 10px 30px rgba(37, 41, 46, 0.2); box-shadow: 0 5px 15px rgba(255, 138, 0, 0.4), 0 10px 30px rgba(37, 41, 46, 0.2); } ` 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 6dbd23fa133b..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 @@ -51,7 +51,7 @@ function NFTAvatarInTwitter() { const ele = searchTwitterAvatarSelector().evaluate() if (ele) { const style = window.getComputedStyle(ele) - return Number(style.width.replace('px', '') ?? 0) + return Number.parseInt(style.width.replace('px', '') ?? 0, 10) } return 0 }, [windowSize])