Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
ProfileIdentifier,
ProfileInformation,
DashboardRoutes,
NextIDPersonaBindings,
NextIDAction,
} from '@masknet/shared-base'
import { useMenu } from '@masknet/shared'
Expand All @@ -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: {
Expand Down Expand Up @@ -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 (
<PersonaRowCardUI
verification={verification}
publicKey={currentPersona.publicHexKey}
nickname={currentPersona.nickname}
identifier={currentPersona.identifier}
profiles={currentPersona.linkedProfiles}
Expand All @@ -95,10 +87,10 @@ export interface PersonaRowCardUIProps {
identifier: PersonaIdentifier
profiles: ProfileInformation[]
definedSocialNetworks: SocialNetwork[]
publicKey: string
onConnect: (identifier: PersonaIdentifier, networkIdentifier: string) => void
onDisconnect: (identifier: ProfileIdentifier) => void
onRename: (identifier: PersonaIdentifier, target: string, callback?: () => void) => Promise<void>
verification?: NextIDPersonaBindings
onDeleteBound: (
identifier: PersonaIdentifier,
profile: ProfileIdentifier,
Expand All @@ -113,12 +105,11 @@ export const PersonaRowCardUI = memo<PersonaRowCardUIProps>((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)
Expand Down Expand Up @@ -205,7 +196,7 @@ export const PersonaRowCardUI = memo<PersonaRowCardUIProps>((props) => {
} else {
return (
<ConnectedPersonaLine
verification={verification}
proof={proof}
disableAdd={currentNetworkProfiles.length >= 5}
isHideOperations={false}
key={networkIdentifier}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand Down Expand Up @@ -60,16 +61,15 @@ export interface PersonaCardProps {
active?: boolean
identifier: PersonaIdentifier
profiles: ProfileInformation[]
publicKey: string
onClick(): void
}

export const PersonaCard = memo<PersonaCardProps>((props) => {
const { connectPersona, disconnectPersona, definedSocialNetworks, verification } = PersonaContext.useContainer()

const { connectPersona, disconnectPersona, definedSocialNetworks } = PersonaContext.useContainer()
return (
<PersonaCardUI
{...props}
verification={verification}
onConnect={connectPersona}
onDisconnect={disconnectPersona}
definedSocialNetworks={definedSocialNetworks}
Expand All @@ -85,10 +85,10 @@ export interface PersonaCardUIProps extends PersonaCardProps {
}

export const PersonaCardUI = memo<PersonaCardUIProps>((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 (
<div className={classes.card}>
<div className={classNames(classes.status, active ? classes.statusActivated : classes.statusInactivated)} />
Expand Down Expand Up @@ -118,7 +118,7 @@ export const PersonaCardUI = memo<PersonaCardUIProps>((props) => {
} else {
return (
<ConnectedPersonaLine
verification={verification}
proof={proof}
isHideOperations
key={networkIdentifier}
onConnect={() => onConnect(identifier, networkIdentifier)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,12 @@ export const PersonaDrawerUI = memo<PersonaDrawerUIProps>(
<Stack justifyContent="space-between" gap={2} height="100%" maxHeight="100%">
<Box overflow="auto">
{personas.map((item) => {
const { identifier, nickname, linkedProfiles } = item
const { identifier, nickname, linkedProfiles, publicHexKey } = item
if (!publicHexKey) return null
return (
<Box mb={2.5} key={identifier.toText()}>
<PersonaCard
publicKey={publicHexKey}
identifier={identifier}
active={identifier.equals(currentPersonaIdentifier)}
key={identifier.toText()}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { Box, Button, Link, Stack, Typography } from '@mui/material'
import { getMaskColor, MaskColorVar, makeStyles } from '@masknet/theme'
import { useDashboardI18N } from '../../../../locales'
import { DisconnectProfileDialog } from '../DisconnectProfileDialog'
import type { NextIDPersonaBindings, PersonaIdentifier, ProfileIdentifier, BindingProof } from '@masknet/shared-base'
import { SOCIAL_MEDIA_ICON_MAPPING } from '@masknet/shared'
import type { PersonaIdentifier, ProfileIdentifier, BindingProof, NextIDPersonaBindings } from '@masknet/shared-base'
import { LoadingAnimation, SOCIAL_MEDIA_ICON_MAPPING } from '@masknet/shared'
import { PersonaContext } from '../../hooks/usePersonaContext'
import { NextIdPersonaWarningIcon, NextIdPersonaVerifiedIcon } from '@masknet/icons'

Expand Down Expand Up @@ -76,8 +76,8 @@ export interface ConnectedPersonaLineProps {
profileIdentifiers: ProfileIdentifier[]
networkIdentifier: string
disableAdd?: boolean
verification?: NextIDPersonaBindings
personaIdentifier: PersonaIdentifier
proof: { loading: boolean; value?: NextIDPersonaBindings }
}

export const ConnectedPersonaLine = memo<ConnectedPersonaLineProps>(
Expand All @@ -89,8 +89,8 @@ export const ConnectedPersonaLine = memo<ConnectedPersonaLineProps>(
networkIdentifier,
isHideOperations,
disableAdd,
verification,
personaIdentifier,
proof,
}) => {
const t = useDashboardI18N()
const { openProfilePage } = PersonaContext.useContainer()
Expand All @@ -109,7 +109,7 @@ export const ConnectedPersonaLine = memo<ConnectedPersonaLineProps>(
}

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) {
Expand All @@ -119,20 +119,26 @@ export const ConnectedPersonaLine = memo<ConnectedPersonaLineProps>(
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 (
<div className={classes.userIdBox}>
<div>@{profile.userId}</div>
<div className={classes.proofIconBox} onClick={(e: MouseEvent) => handleProofIconClick(e, proof)}>
{!proofSupport ? null : proof?.is_valid ? (
<NextIdPersonaVerifiedIcon />
) : (
<NextIdPersonaWarningIcon />
)}
</div>
{profile.network === 'twitter.com' && (
<div
className={classes.proofIconBox}
onClick={(e: MouseEvent) => handleProofIconClick(e, isProved)}>
{proof.loading ? (
<LoadingAnimation />
) : isProved?.is_valid ? (
<NextIdPersonaVerifiedIcon />
) : (
<NextIdPersonaWarningIcon />
)}
</div>
)}
</div>
)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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) => {
Expand All @@ -22,5 +22,6 @@ export function useDeleteBound() {
signature: signature,
})
Services.Identity.detachProfile(profile)
Messages.events.ownProofChanged.sendToAll(undefined)
})
}
12 changes: 0 additions & 12 deletions packages/dashboard/src/pages/Personas/hooks/usePersonaContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,15 @@ 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() {
const currentPersonaIdentifier = useCurrentPersonaIdentifier()
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()
Expand All @@ -45,7 +34,6 @@ function usePersonaContext() {
openProfilePage,
drawerOpen: open,
toggleDrawer: () => setOpen((e) => !e),
verification,
}
}

Expand Down
12 changes: 12 additions & 0 deletions packages/dashboard/src/pages/Personas/hooks/usePersonaProof.ts
Original file line number Diff line number Diff line change
@@ -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
}
Original file line number Diff line number Diff line change
Expand Up @@ -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 () => {
Expand Down Expand Up @@ -155,6 +154,7 @@ function SetupGuideUI(props: SetupGuideUIProps) {
})

await waitingPost
MaskMessages.events.ownProofChanged.sendToAll(undefined)
}
}

Expand Down
1 change: 1 addition & 0 deletions packages/shared-base/src/Messages/Mask.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<ProfileIdentifier>[]
relationsChanged: RelationChangedEvent[]
Expand Down
3 changes: 2 additions & 1 deletion packages/shared-base/src/Persona/type.ts
Original file line number Diff line number Diff line change
@@ -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
Expand Down