Skip to content

Commit

Permalink
fix: bugfix for encrypted contacts (#10413)
Browse files Browse the repository at this point in the history
* fix: mf-4909 input style

* feat: add load more

* fix: add persona contact

* fix: self in contacts

* feat: add persona relation

* fix: empty detail

* fix: mf-4922 search value

* chore: remove debug code

* fix: type error

* chore: code review

* chore: code review

* chore: code rewiew

* chore: remove unused
  • Loading branch information
beyond009 committed Aug 16, 2023
1 parent 29237fe commit c5c31cd
Show file tree
Hide file tree
Showing 19 changed files with 238 additions and 132 deletions.
3 changes: 2 additions & 1 deletion packages/backup-format/src/normalize/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import type {
ProfileIdentifier,
RelationFavor,
PostIVIdentifier,
ECKeyIdentifier,
} from '@masknet/shared-base'
import type { Option } from 'ts-results-es'

Expand Down Expand Up @@ -55,7 +56,7 @@ export namespace NormalizedBackup {
updatedAt: Option<Date>
}
export interface RelationBackup {
profile: ProfileIdentifier
profile: ProfileIdentifier | ECKeyIdentifier
persona: PersonaIdentifier
favor: RelationFavor
}
Expand Down
5 changes: 3 additions & 2 deletions packages/dashboard/src/pages/Personas/hooks/useContacts.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { useAsyncRetry, useUpdateEffect } from 'react-use'
import { Services } from '../../../API.js'
import type { ProfileInformation, Relation, RelationFavor } from '@masknet/shared-base'
import type { ProfileInformation, RelationFavor, Relation } from '@masknet/shared-base'
import { useRef } from 'react'
import { last } from 'lodash-es'
import { PersonaContext } from './usePersonaContext.js'
import type { AsyncStateRetry } from 'react-use/lib/useAsyncRetry.js'
import { isProfileIdentifier } from '@masknet/shared'

export interface Contacts extends ProfileInformation {
favor: RelationFavor | undefined
Expand Down Expand Up @@ -37,7 +38,7 @@ export function useContacts(network: string, page: number, size = 20): AsyncStat

if (values.length === 0) return []

const identifiers = values.map((x) => x.profile)
const identifiers = values.map((x) => x.profile).filter(isProfileIdentifier)
const [avatars, profiles] = await Promise.all([
Services.Identity.queryAvatarsDataURL(identifiers),
Services.Identity.queryProfilesInformation(identifiers),
Expand Down
6 changes: 3 additions & 3 deletions packages/mask/background/database/persona/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ type PersonaIdentifierStoredInDB = {

/** @internal */
export type RelationRecordDB = Omit<RelationRecord, 'profile' | 'linked'> & {
network: string
network?: string
profile: string
linked: string
}
Expand Down Expand Up @@ -100,9 +100,9 @@ export interface PersonaDB extends DBSchema {
}

export interface RelationRecord {
profile: ProfileIdentifier
profile: ProfileIdentifier | PersonaIdentifier
linked: PersonaIdentifier
network: string
network?: string
favor: RelationFavor
}

Expand Down
47 changes: 34 additions & 13 deletions packages/mask/background/database/persona/web.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import type {
RelationRecordDB,
PersonaRecord,
} from './type.js'

/**
* Database structure:
*
Expand Down Expand Up @@ -717,23 +718,43 @@ function personaRecordOutDB(x: PersonaRecordDB): PersonaRecord {
}

function relationRecordToDB(x: Omit<RelationRecord, 'network'>): RelationRecordDB {
return {
...x,
network: x.profile.network,
profile: x.profile.toText(),
linked: x.linked.toText(),
if (x.profile instanceof ProfileIdentifier) {
return {
...x,
network: x.profile.network,
profile: x.profile.toText(),
linked: x.linked.toText(),
}
} else {
return {
...x,
profile: x.profile.toText(),
linked: x.linked.toText(),
}
}
}

function relationRecordOutDB(x: RelationRecordDB): RelationRecord {
return {
...x,
profile: ProfileIdentifier.from(x.profile).expect(
`data stored in the profile database should be a valid ProfileIdentifier, but found ${x.profile}`,
),
linked: ECKeyIdentifier.from(x.linked).expect(
`data stored in the profile database should be a valid ECKeyIdentifier, but found ${x.linked}`,
),
if (x.profile.startsWith('person:')) {
return {
...x,
profile: ProfileIdentifier.from(x.profile).expect(
`data stored in the profile database should be a valid ProfileIdentifier, but found ${x.profile}`,
),
linked: ECKeyIdentifier.from(x.linked).expect(
`data stored in the profile database should be a valid ECKeyIdentifier, but found ${x.linked}`,
),
}
} else {
return {
...x,
profile: ECKeyIdentifier.from(x.profile).expect(
`data stored in the profile database should be a valid ECKeyIdentifier, but found ${x.profile}`,
),
linked: ECKeyIdentifier.from(x.linked).expect(
`data stored in the profile database should be a valid ECKeyIdentifier, but found ${x.linked}`,
),
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { ProfileIdentifier, PersonaIdentifier } from '@masknet/shared-base'
import { createRelationsTransaction, createRelationDB } from '../../../database/persona/db.js'

export async function createNewRelation(
profile: ProfileIdentifier,
profile: ProfileIdentifier | PersonaIdentifier,
linked: PersonaIdentifier,
favor = RelationFavor.UNCOLLECTED,
): Promise<void> {
Expand Down
1 change: 1 addition & 0 deletions packages/mask/shared-ui/locales/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -1059,6 +1059,7 @@
"popups_encrypted_friends_search_no_result": "No search results",
"popups_encrypted_friends_no_friends": "No encrypted friends, you can try searching.",
"popups_encrypted_friends_add_friends": "Add",
"popups_encrypted_friends_no_associated_accounts": "No associated accounts",
"popups_select_wallet": "Select Wallet",
"popups_switch_persona": "Switch Persona",
"popups_recovery": "Recovery",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { EMPTY_LIST, type ProfileInformation } from '@masknet/shared-base'
import type { AsyncStateRetry } from 'react-use/lib/useAsyncRetry.js'
import { useCurrentPersona } from '../../DataSource/useCurrentPersona.js'
import Services from '../../../extension/service.js'
import { isProfileIdentifier } from '@masknet/shared'

export function useContacts(network: string): AsyncStateRetry<ProfileInformation[]> {
const currentPersona = useCurrentPersona()
Expand All @@ -18,7 +19,7 @@ export function useContacts(network: string): AsyncStateRetry<ProfileInformation
)
if (values.length === 0) return EMPTY_LIST

const identifiers = values.map((x) => x.profile)
const identifiers = values.map((x) => x.profile).filter(isProfileIdentifier)
return Services.Identity.queryProfilesInformation(identifiers)
}, [network, currentPersona])
}
81 changes: 58 additions & 23 deletions packages/mask/src/extension/popups/hook/useFriends.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,27 @@ import {
type ECKeyIdentifier,
EMPTY_LIST,
type BindingProof,
type ProfileInformation,
NextIDPlatform,
type ProfileIdentifier,
} from '@masknet/shared-base'
import type { AsyncStateRetry } from 'react-use/lib/useAsyncRetry.js'
import { useCurrentPersona } from '../../../components/DataSource/useCurrentPersona.js'
import Services from '../../../extension/service.js'
import { NextIDProof } from '@masknet/web3-providers'
import { uniqBy } from 'lodash-es'
import { first, uniqBy } from 'lodash-es'
import { isProfileIdentifier } from '@masknet/shared'

export type FriendsInformation = ProfileInformation & {
export type FriendsInformation = Friend & {
profiles: BindingProof[]
id: string
}

type Friend = {
persona: ECKeyIdentifier
profile?: ProfileIdentifier
avatar?: string
}

export const PlatformSort: Record<NextIDPlatform, number> = {
[NextIDPlatform.Twitter]: 0,
[NextIDPlatform.GitHub]: 1,
Expand All @@ -36,6 +43,10 @@ export const PlatformSort: Record<NextIDPlatform, number> = {
[NextIDPlatform.NextID]: 15,
}

function emptyFilter(x: Friend | undefined): x is Friend {
return x !== undefined
}

export function useFriends(): AsyncStateRetry<FriendsInformation[]> {
const currentPersona = useCurrentPersona()
return useAsyncRetry(async () => {
Expand All @@ -48,30 +59,54 @@ export function useFriends(): AsyncStateRetry<FriendsInformation[]> {
1000,
)
if (values.length === 0) return EMPTY_LIST
const friends = (await Services.Identity.queryProfilesInformation(values.map((x) => x.profile))).filter(
(item) => item.linkedPersona !== undefined,
)
const friends: Friend[] = (
await Promise.all<Promise<Friend | undefined>>(
values.map(async (x) => {
if (isProfileIdentifier(x.profile)) {
const res = first(await Services.Identity.queryProfilesInformation([x.profile]))
if (res?.linkedPersona !== undefined && res?.linkedPersona !== currentPersona?.identifier)
return {
persona: res.linkedPersona,
profile: x.profile,
avatar: res.avatar,
}
return
} else {
if (x.profile !== currentPersona?.identifier) return { persona: x.profile }
return
}
}),
)
).filter(emptyFilter)
const allSettled = await Promise.allSettled(
friends.map((item) => {
const id = (item.linkedPersona as ECKeyIdentifier).publicKeyAsHex
const id = item.persona.publicKeyAsHex
return NextIDProof.queryProfilesByPublicKey(id, 2)
}),
)
const profiles: FriendsInformation[] = allSettled.map((item, index) => {
if (!(item.status !== 'rejected')) {
return {
profiles: [
{
platform: NextIDPlatform.Twitter,
identity: friends[index].identifier.userId,
is_valid: true,
last_checked_at: '',
name: friends[index].identifier.userId,
created_at: '',
},
],
...friends[index],
id: (friends[index].linkedPersona as ECKeyIdentifier).publicKeyAsHex,
if (item.status === 'rejected') {
if (friends[index].profile) {
return {
profiles: [
{
platform: NextIDPlatform.Twitter,
identity: friends[index].profile!.userId,
is_valid: true,
last_checked_at: '',
name: friends[index].profile!.userId,
created_at: '',
},
],
...friends[index],
id: friends[index].persona.publicKeyAsHex,
}
} else {
return {
profiles: [],
...friends[index],
id: friends[index].persona.publicKeyAsHex,
}
}
}
const filtered = item.value.filter(
Expand All @@ -89,9 +124,9 @@ export function useFriends(): AsyncStateRetry<FriendsInformation[]> {
return {
profiles: filtered,
...friends[index],
id: (friends[index].linkedPersona as ECKeyIdentifier).publicKeyAsHex,
id: friends[index].persona.publicKeyAsHex,
}
})
return uniqBy(profiles, ({ id }) => id).reverse()
return uniqBy(profiles, ({ id }) => id)
}, [currentPersona])
}
12 changes: 5 additions & 7 deletions packages/mask/src/extension/popups/hook/useFriendsFromSearch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,16 @@ export function useFriendsFromSearch(
const identifier = ECKeyIdentifier.fromHexPublicKeyK256(item.persona).expect(
`${item.persona} should be a valid hex public key in k256`,
)
filtered.sort((a, b) =>
a.identity === searchValue || a.name === searchValue
? -1
: PlatformSort[a.platform] - PlatformSort[b.platform],
)
filtered.sort((a, b) => PlatformSort[a.platform] - PlatformSort[b.platform])
const searchItem = filtered.findIndex((x) => x.identity === searchValue || x.name === searchValue)
if (searchItem !== -1) filtered.unshift(filtered.splice(searchItem, 1)[0])
return {
proofs: filtered,
proofs: uniqBy(filtered, ({ identity }) => identity),
linkedPersona: identifier,
activated_at: item.activated_at,
persona: item.persona,
isLocal: localList
? localList.some((x) => x.linkedPersona?.publicKeyAsHex === identifier.publicKeyAsHex)
? localList.some((x) => x.persona.publicKeyAsHex === identifier.publicKeyAsHex)
: false,
}
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { NextIDPlatform } from '@masknet/shared-base'
import { attachNextIDToProfile } from '../../../../../utils/utils.js'
import { ConnectedAccounts } from './ConnectedAccounts/index.js'
import { useI18N } from '../../../../../utils/i18n-next-ui.js'
import Services from '../../../../service.js'

const useStyles = makeStyles()((theme) => ({
card: {
Expand Down Expand Up @@ -88,17 +89,20 @@ export const ContactCard = memo<ContactCardProps>(function ContactCard({
const handleAddFriend = useCallback(async () => {
if (!currentPersona) return
const twitter = profiles.find((p) => p.platform === NextIDPlatform.Twitter)
if (!twitter) return
const profileIdentifier = ProfileIdentifier.of('twitter.com', twitter.identity).unwrap()
const personaIdentifier = ECKeyIdentifier.fromHexPublicKeyK256(nextId).expect(
`${nextId} should be a valid hex public key in k256`,
)
await attachNextIDToProfile({
identifier: profileIdentifier,
linkedPersona: personaIdentifier,
fromNextID: true,
linkedTwitterNames: [twitter.identity],
})
if (!twitter) {
await Services.Identity.createNewRelation(personaIdentifier, currentPersona.identifier)
} else {
const profileIdentifier = ProfileIdentifier.of('twitter.com', twitter.identity).unwrap()
await attachNextIDToProfile({
identifier: profileIdentifier,
linkedPersona: personaIdentifier,
fromNextID: true,
linkedTwitterNames: twitter ? [twitter.identity] : [],
})
}
setLocal(true)
}, [profiles, nextId, currentPersona])

Expand Down

0 comments on commit c5c31cd

Please sign in to comment.