diff --git a/packages/dashboard/src/pages/Personas/components/PersonaCard/Row.tsx b/packages/dashboard/src/pages/Personas/components/PersonaCard/Row.tsx index 62459bbf4d72..4bc0b1c6d8b3 100644 --- a/packages/dashboard/src/pages/Personas/components/PersonaCard/Row.tsx +++ b/packages/dashboard/src/pages/Personas/components/PersonaCard/Row.tsx @@ -8,7 +8,6 @@ import { ProfileIdentifier, ProfileInformation, DashboardRoutes, - NextIDPersonaBindings, NextIDAction, } from '@masknet/shared-base' import { useMenu } from '@masknet/shared' @@ -26,6 +25,7 @@ import { styled } from '@mui/material/styles' import { PreviewDialog as ExportPersonaDialog } from '../../../SignUp/steps/PreviewDialog' import { useExportPrivateKey } from '../../hooks/useExportPrivateKey' import { useExportMnemonicWords } from '../../hooks/useExportMnemonicWords' +import { usePersonaProof } from '../../hooks/usePersonaProof' const useStyles = makeStyles()((theme) => ({ setting: { @@ -63,21 +63,13 @@ const MenuText = styled('span')(` `) export const PersonaRowCard = memo(() => { - const { - currentPersona, - connectPersona, - disconnectPersona, - renamePersona, - deleteBound, - definedSocialNetworks, - verification, - } = PersonaContext.useContainer() - - if (!currentPersona) return null + const { currentPersona, connectPersona, disconnectPersona, renamePersona, deleteBound, definedSocialNetworks } = + PersonaContext.useContainer() + if (!currentPersona || !currentPersona.publicHexKey) return null return ( void onDisconnect: (identifier: ProfileIdentifier) => void onRename: (identifier: PersonaIdentifier, target: string, callback?: () => void) => Promise - verification?: NextIDPersonaBindings onDeleteBound: ( identifier: PersonaIdentifier, profile: ProfileIdentifier, @@ -113,12 +105,11 @@ export const PersonaRowCardUI = memo((props) => { const { classes } = useStyles() const { confirmPassword } = useContext(UserContext) - const { nickname, definedSocialNetworks, identifier, profiles, verification } = props + const { nickname, definedSocialNetworks, identifier, profiles, publicKey } = props const { onConnect, onDisconnect, onRename, onDeleteBound } = props - const { value: privateKey } = useExportPrivateKey(identifier) const { value: words } = useExportMnemonicWords(identifier) - + const proof = usePersonaProof(publicKey) const [avatarOn, toggleAvatar] = useToggle(false) const [renameDialogOpen, setRenameDialogOpen] = useState(false) const [logoutDialogOpen, setLogoutDialogOpen] = useState(false) @@ -205,7 +196,7 @@ export const PersonaRowCardUI = memo((props) => { } else { return ( = 5} isHideOperations={false} key={networkIdentifier} diff --git a/packages/dashboard/src/pages/Personas/components/PersonaCard/index.tsx b/packages/dashboard/src/pages/Personas/components/PersonaCard/index.tsx index 79964aeea168..08402339468e 100644 --- a/packages/dashboard/src/pages/Personas/components/PersonaCard/index.tsx +++ b/packages/dashboard/src/pages/Personas/components/PersonaCard/index.tsx @@ -12,6 +12,7 @@ import { formatFingerprint } from '@masknet/shared' import { PersonaContext } from '../../hooks/usePersonaContext' import type { SocialNetwork } from '../../api' import classNames from 'classnames' +import { usePersonaProof } from '../../hooks/usePersonaProof' const useStyles = makeStyles()((theme) => ({ card: { @@ -60,16 +61,15 @@ export interface PersonaCardProps { active?: boolean identifier: PersonaIdentifier profiles: ProfileInformation[] + publicKey: string onClick(): void } export const PersonaCard = memo((props) => { - const { connectPersona, disconnectPersona, definedSocialNetworks, verification } = PersonaContext.useContainer() - + const { connectPersona, disconnectPersona, definedSocialNetworks } = PersonaContext.useContainer() return ( ((props) => { - const { nickname, active = false, definedSocialNetworks, identifier, profiles, verification } = props + const { nickname, active = false, definedSocialNetworks, identifier, profiles, publicKey } = props const { onConnect, onDisconnect, onClick } = props const { classes } = useStyles() - + const proof = usePersonaProof(publicKey) return (
@@ -118,7 +118,7 @@ export const PersonaCardUI = memo((props) => { } else { return ( onConnect(identifier, networkIdentifier)} diff --git a/packages/dashboard/src/pages/Personas/components/PersonaDrawer/index.tsx b/packages/dashboard/src/pages/Personas/components/PersonaDrawer/index.tsx index 3804da3758dc..a28f8b73a0ea 100644 --- a/packages/dashboard/src/pages/Personas/components/PersonaDrawer/index.tsx +++ b/packages/dashboard/src/pages/Personas/components/PersonaDrawer/index.tsx @@ -83,10 +83,12 @@ export const PersonaDrawerUI = memo( {personas.map((item) => { - const { identifier, nickname, linkedProfiles } = item + const { identifier, nickname, linkedProfiles, publicHexKey } = item + if (!publicHexKey) return null return ( ( @@ -89,8 +89,8 @@ export const ConnectedPersonaLine = memo( networkIdentifier, isHideOperations, disableAdd, - verification, personaIdentifier, + proof, }) => { const t = useDashboardI18N() const { openProfilePage } = PersonaContext.useContainer() @@ -109,7 +109,7 @@ export const ConnectedPersonaLine = memo( } const handleDisconnect = (profile: ProfileIdentifier) => { - const isProved = verification?.proofs.find((x) => { + const isProved = proof.value?.proofs.find((x) => { return x.platform === 'twitter' && x.identity === profile.userId.toLowerCase() }) if (isProved && onDeleteBound) { @@ -119,20 +119,26 @@ export const ConnectedPersonaLine = memo( onDisconnect(profile) } const userIdBox = (profile: ProfileIdentifier) => { - const proofSupport = ['twitter.com'].includes(profile.network) - const proof = verification?.proofs.find((x) => { + const isProved = proof.value?.proofs.find((x) => { return x.platform === 'twitter' && x.identity === profile.userId.toLowerCase() }) + return (
@{profile.userId}
-
handleProofIconClick(e, proof)}> - {!proofSupport ? null : proof?.is_valid ? ( - - ) : ( - - )} -
+ {profile.network === 'twitter.com' && ( +
handleProofIconClick(e, isProved)}> + {proof.loading ? ( + + ) : isProved?.is_valid ? ( + + ) : ( + + )} +
+ )}
) } diff --git a/packages/dashboard/src/pages/Personas/hooks/useOperateBindingProof.ts b/packages/dashboard/src/pages/Personas/hooks/useOperateBindingProof.ts index 25bda7a11f38..68636214c2d9 100644 --- a/packages/dashboard/src/pages/Personas/hooks/useOperateBindingProof.ts +++ b/packages/dashboard/src/pages/Personas/hooks/useOperateBindingProof.ts @@ -1,7 +1,7 @@ import type { ECKeyIdentifier } from '@masknet/shared-base' import { bindProof, createPersonaPayload } from '@masknet/web3-providers' import { useAsyncFn } from 'react-use' -import { Services } from '../../../API' +import { Services, Messages } from '../../../API' export function useDeleteBound() { return useAsyncFn(async (identifier: ECKeyIdentifier, profile, network, action) => { @@ -22,5 +22,6 @@ export function useDeleteBound() { signature: signature, }) Services.Identity.detachProfile(profile) + Messages.events.ownProofChanged.sendToAll(undefined) }) } diff --git a/packages/dashboard/src/pages/Personas/hooks/usePersonaContext.ts b/packages/dashboard/src/pages/Personas/hooks/usePersonaContext.ts index b3154d7e458d..cbbfb8cd6734 100644 --- a/packages/dashboard/src/pages/Personas/hooks/usePersonaContext.ts +++ b/packages/dashboard/src/pages/Personas/hooks/usePersonaContext.ts @@ -4,9 +4,6 @@ import { useConnectSocialNetwork, useDisconnectSocialNetwork, useOpenProfilePage import { Services } from '../../../API' import { useOwnedPersonas, useDefinedSocialNetworkUIs, SocialNetwork, useCurrentPersonaIdentifier } from '../api' import { useCreatePersona } from './useCreatePersona' -import { queryExistedBindingByPersona } from '@masknet/web3-providers' -import { useAsync, useAsyncRetry } from 'react-use' -import type { ECKeyIdentifier } from '@masknet/shared-base' import { useDeleteBound } from './useOperateBindingProof' function usePersonaContext() { @@ -14,16 +11,8 @@ function usePersonaContext() { const definedSocialNetworks: SocialNetwork[] = useDefinedSocialNetworkUIs() const personas = useOwnedPersonas() const currentPersona = personas.find((x) => x.identifier.equals(currentPersonaIdentifier)) - const [open, setOpen] = useState(false) - const personaPublicKey = useAsync(async () => { - return Services.Identity.queryPersona(currentPersonaIdentifier as ECKeyIdentifier) - }, [currentPersonaIdentifier]).value?.publicHexKey - const verification = useAsyncRetry(async () => { - return queryExistedBindingByPersona(personaPublicKey as string) - }, [personaPublicKey]).value - const [, connectPersona] = useConnectSocialNetwork() const [, openProfilePage] = useOpenProfilePage() const [, disconnectPersona] = useDisconnectSocialNetwork() @@ -45,7 +34,6 @@ function usePersonaContext() { openProfilePage, drawerOpen: open, toggleDrawer: () => setOpen((e) => !e), - verification, } } diff --git a/packages/dashboard/src/pages/Personas/hooks/usePersonaProof.ts b/packages/dashboard/src/pages/Personas/hooks/usePersonaProof.ts new file mode 100644 index 000000000000..845204bdcdb1 --- /dev/null +++ b/packages/dashboard/src/pages/Personas/hooks/usePersonaProof.ts @@ -0,0 +1,12 @@ +import { queryExistedBindingByPersona } from '@masknet/web3-providers' +import { useEffect } from 'react' +import { useAsyncRetry } from 'react-use' +import { Messages } from '../../../API' + +export function usePersonaProof(publicHexKey: string) { + const res = useAsyncRetry(async () => { + return queryExistedBindingByPersona(publicHexKey) + }, [publicHexKey]) + useEffect(() => Messages.events.ownProofChanged.on(res.retry), [res.retry]) + return res +} diff --git a/packages/mask/src/components/InjectedComponents/SetupGuide.tsx b/packages/mask/src/components/InjectedComponents/SetupGuide.tsx index 6fc6378e4820..82ec465f3bb5 100644 --- a/packages/mask/src/components/InjectedComponents/SetupGuide.tsx +++ b/packages/mask/src/components/InjectedComponents/SetupGuide.tsx @@ -111,7 +111,6 @@ function SetupGuideUI(props: SetupGuideUIProps) { // auto-finish the setup process if (!persona_?.hasPrivateKey) throw new Error('invalid persona') await Services.Identity.setupPersona(persona_?.identifier) - MaskMessages.events.ownPersonaChanged.sendToAll(undefined) } const onVerify = async () => { @@ -155,6 +154,7 @@ function SetupGuideUI(props: SetupGuideUIProps) { }) await waitingPost + MaskMessages.events.ownProofChanged.sendToAll(undefined) } } diff --git a/packages/shared-base/src/Messages/Mask.ts b/packages/shared-base/src/Messages/Mask.ts index b3d5fc4b1237..d1d176621393 100644 --- a/packages/shared-base/src/Messages/Mask.ts +++ b/packages/shared-base/src/Messages/Mask.ts @@ -58,6 +58,7 @@ export interface MaskEvents extends MaskSettingsEvents, MaskMobileOnlyEvents, Ma /** emit when the settings finished syncing with storage. */ createInternalSettingsUpdated: SettingsUpdateEvent ownPersonaChanged: void + ownProofChanged: void restoreSuccess: void profilesChanged: UpdateEvent[] relationsChanged: RelationChangedEvent[] diff --git a/packages/shared-base/src/Persona/type.ts b/packages/shared-base/src/Persona/type.ts index fe5ccf8c9cb3..23661ec52320 100644 --- a/packages/shared-base/src/Persona/type.ts +++ b/packages/shared-base/src/Persona/type.ts @@ -1,9 +1,10 @@ import type { PersonaIdentifier, ProfileIdentifier } from '../Identifier/type' - +import type { NextIDPersonaBindings } from '../NextID/type' /** * This interface contains the minimal information for UI display */ export interface PersonaInformation { + proof?: NextIDPersonaBindings /** The nickname of the persona. Should use profile.nickname if it presents. */ nickname?: string publicHexKey?: string