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
1 change: 1 addition & 0 deletions packages/dashboard/src/web3/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ export const Web3Context: Web3ProviderType = {
),
getAssetsList: PluginServices.Wallet.getAssetsList,
getAssetsListNFT: PluginServices.Wallet.getAssetsListNFT,
getAddressNamesList: PluginServices.Wallet.getAddressNames,
getERC721TokensPaged,
getTransactionList: PluginServices.Wallet.getTransactionList,
fetchERC20TokensFromTokenLists: Services.Ethereum.fetchERC20TokensFromTokenLists,
Expand Down
9 changes: 7 additions & 2 deletions packages/maskbook/src/components/DataSource/useActivatedUI.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useMemo } from 'react'
import { ValueRef } from '@dimensiondev/holoflows-kit'
import { ProfileIdentifier, useValueRef } from '@masknet/shared'
import { useMemo } from 'react'
import type { Profile } from '../../database'
import { currentSelectedIdentity } from '../../settings/settings'
import type { SocialNetworkUI } from '../../social-network'
Expand All @@ -14,7 +14,12 @@ export function useFriendsList() {
const default_ = new ValueRef({ identifier: ProfileIdentifier.unknown })
export function useLastRecognizedIdentity() {
return useValueRef<SocialNetworkUI.CollectingCapabilities.IdentityResolved>(
activatedSocialNetworkUI.collecting.identityProvider?.lastRecognized || default_,
activatedSocialNetworkUI.collecting.identityProvider?.recognized || default_,
)
}
export function useCurrentVisitingIdentity() {
return useValueRef<SocialNetworkUI.CollectingCapabilities.IdentityResolved>(
activatedSocialNetworkUI.collecting.currentVisitingIdentityProvider?.recognized || default_,
)
}
export function useMyIdentities() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -551,7 +551,7 @@ function SetupGuideUI(props: SetupGuideUIProps) {
const [username, setUsername] = useState(getUsername)
useEffect(
() =>
activatedSocialNetworkUI.collecting.identityProvider?.lastRecognized.addListener((val) => {
activatedSocialNetworkUI.collecting.identityProvider?.recognized.addListener((val) => {
if (username === '' && !val.identifier.isUnknown) setUsername(val.identifier.userId)
}),
[username],
Expand Down
1 change: 1 addition & 0 deletions packages/maskbook/src/database/Persona/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ type TypedOmit<T, Q extends keyof T> = Omit<T, Q>
export interface Profile extends Readonly<TypedOmit<ProfileRecord, 'localKey' | 'linkedPersona'>> {
readonly linkedPersona?: Persona
readonly avatar?: string
readonly bio?: string
}

export interface Persona extends TypedOmit<PersonaRecord, 'localKey' | 'publicKey' | 'privateKey' | 'linkedProfiles'> {
Expand Down
38 changes: 38 additions & 0 deletions packages/maskbook/src/plugins/Wallet/apis/ens.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import stringify from 'json-stable-stringify'

async function fetchFromENSTextResolverSubgraph<T>(query: string) {
const subgraphURL = 'https://api.thegraph.com/subgraphs/name/dimensiondev/ens-text-resolver-subgraph'
const response = await fetch(subgraphURL, {
method: 'POST',
mode: 'cors',
body: stringify({ query }),
})
const { data } = (await response.json()) as {
data: T
}
return data
}

export async function fetchAddressNamesByTwitterId(twitterId: string) {
const data = await fetchFromENSTextResolverSubgraph<{
twitterHandle?: {
domains: {
id: string
owner: string
}[]
}
}>(`
query twitterHandle {
twitterHandle(id: "${twitterId}") {
id
raw
domains {
id
owner
}
}
}
`)
if (!data?.twitterHandle) return []
return data.twitterHandle.domains
}
4 changes: 2 additions & 2 deletions packages/maskbook/src/plugins/Wallet/services/assets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export async function getAssetsListNFT(
assets: assets
.filter(
(x) =>
x.asset_contract.asset_contract_type === 'non-fungible' ||
['non-fungible', 'semi-fungible'].includes(x.asset_contract.asset_contract_type) ||
['ERC721', 'ERC1155'].includes(x.asset_contract.schema_name),
)
.map((x) =>
Expand All @@ -62,7 +62,7 @@ export async function getAssetsListNFT(
{
name: x.name,
description: x.description,
image: x.image_url ?? x.image_preview_url ?? '',
image: x.image_url ?? x.image_preview_url ?? x.asset_contract.image_url ?? '',
},
x.token_id,
),
Expand Down
22 changes: 22 additions & 0 deletions packages/maskbook/src/plugins/Wallet/services/domain.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { memoizePromise, unreachable } from '@dimensiondev/kit'
import { AddressNameType, AddressName } from '@masknet/web3-shared'
import * as ENS from '../apis/ens'

const fetchAddressNamesByTwitterIdCached = memoizePromise(ENS.fetchAddressNamesByTwitterId, (twitterId) => twitterId)

export async function getAddressNames(twitterId: string, addressNameType: AddressNameType): Promise<AddressName[]> {
switch (addressNameType) {
case AddressNameType.ENS:
return (await fetchAddressNamesByTwitterIdCached(twitterId)).map((x) => ({
label: '',
ownerAddress: x.owner,
resolvedAddress: x.owner,
}))
case AddressNameType.UNS:
throw new Error('To be implemented.')
case AddressNameType.DNS:
throw new Error('To be implemented.')
default:
unreachable(addressNameType)
}
}
1 change: 1 addition & 0 deletions packages/maskbook/src/plugins/Wallet/services/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@ export * from './recentTransactions'
export * from './rpc'
export * from './keystore'
export * from './chain'
export * from './domain'
export * from './cloud'
export { decryptWallet, createEncryptedWalletStore } from '../database/decrypt'
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ import { ProfileIdentifier } from '../../../database/type'

export const IdentityProviderFacebook: SocialNetworkUI.CollectingCapabilities.IdentityResolveProvider = {
hasDeprecatedPlaceholderName: true,
lastRecognized: creator.IdentityResolveProviderLastRecognized(),
recognized: creator.EmptyIdentityResolveProviderState(),
start(signal) {
resolveLastRecognizedIdentityFacebookInner(this.lastRecognized, signal)
resolveLastRecognizedIdentityFacebookInner(this.recognized, signal)
},
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const posts = new LiveSelector().querySelectorAll<HTMLDivElement>(
)

export const PostProviderFacebook: Next.CollectingCapabilities.PostsProvider = {
posts: creator.PostProviderStore(),
posts: creator.EmptyPostProviderState(),
start(signal) {
collectPostsFacebookInner(this.posts, signal)
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ const facebookUI: SocialNetworkUI.Definition = {
// ! Change this might be a breaking change !
return new ProfileIdentifier(
'facebook.com',
ProfileIdentifier.getUserName(IdentityProviderFacebook.lastRecognized.value.identifier) ||
ProfileIdentifier.getUserName(IdentityProviderFacebook.recognized.value.identifier) ||
ProfileIdentifier.getUserName(currentSelectedIdentity[facebookBase.networkIdentifier].value) ||
ProfileIdentifier.getUserName(globalUIState.profiles.value[0].identifier) ||
unreachable('Cannot figure out password' as never),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { instagramBase } from '../base'
import { openDB } from 'idb'
export const IdentityProviderInstagram: SocialNetworkUI.CollectingCapabilities.IdentityResolveProvider = {
async start(signal) {
const ref = this.lastRecognized
const ref = this.recognized
update()

async function update() {
Expand All @@ -14,7 +14,7 @@ export const IdentityProviderInstagram: SocialNetworkUI.CollectingCapabilities.I
setTimeout(update, 10 * 1000)
}
},
lastRecognized: creator.IdentityResolveProviderLastRecognized(),
recognized: creator.EmptyIdentityResolveProviderState(),
}

async function query(): Promise<null | SocialNetworkUI.CollectingCapabilities.IdentityResolved> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const posts = new LiveSelector().querySelectorAll<HTMLDivElement>(
)

export const PostProviderInstagram: SocialNetworkUI.CollectingCapabilities.PostsProvider = {
posts: creator.PostProviderStore(),
posts: creator.EmptyPostProviderState(),
start(signal) {
collectPostsInstagramInner(this.posts, signal)
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { mindsBase } from '../base'
import { handleSelector, selfInfoSelectors } from '../utils/selector'

async function resolveLastRecognizedIdentityInner(
ref: Next.CollectingCapabilities.IdentityResolveProvider['lastRecognized'],
ref: Next.CollectingCapabilities.IdentityResolveProvider['recognized'],
cancel: AbortSignal,
) {
await untilDocumentReady()
Expand Down Expand Up @@ -36,8 +36,8 @@ async function resolveLastRecognizedIdentityInner(

export const IdentityProviderMinds: Next.CollectingCapabilities.IdentityResolveProvider = {
hasDeprecatedPlaceholderName: false,
lastRecognized: creator.IdentityResolveProviderLastRecognized(),
recognized: creator.EmptyIdentityResolveProviderState(),
start(cancel) {
resolveLastRecognizedIdentityInner(this.lastRecognized, cancel)
resolveLastRecognizedIdentityInner(this.recognized, cancel)
},
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { postParser } from '../utils/fetch'
import { postContentSelector } from '../utils/selector'

export const PostProviderMinds: Next.CollectingCapabilities.PostsProvider = {
posts: creator.PostProviderStore(),
posts: creator.EmptyPostProviderState(),
start(signal) {
collectPostsMindsInner(this.posts, signal)
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ const mindsUI: SocialNetworkUI.Definition = {
// ! Change this might be a breaking change !
return new ProfileIdentifier(
'minds.com',
ProfileIdentifier.getUserName(IdentityProviderMinds.lastRecognized.value.identifier) ||
ProfileIdentifier.getUserName(IdentityProviderMinds.recognized.value.identifier) ||
ProfileIdentifier.getUserName(currentSelectedIdentity[mindsBase.networkIdentifier].value) ||
ProfileIdentifier.getUserName(globalUIState.profiles.value[0].identifier) ||
unreachable('Cannot figure out password' as never),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { selfInfoSelectors } from '../utils/selector'
import { isNil } from 'lodash-es'
import { MutationObserverWatcher } from '@dimensiondev/holoflows-kit'
import { selfInfoSelectors, searchProfileTabListSelector } from '../utils/selector'
import { ProfileIdentifier } from '../../../database/type'
import { isNil } from 'lodash-es'
import { creator, SocialNetworkUI as Next } from '../../../social-network'
import { twitterBase } from '../base'
import { getAvatar, getBioDescription, getNickname, getTwitterId } from '../utils/user'
import { delay } from '@masknet/shared-base'

function resolveLastRecognizedIdentityInner(
ref: Next.CollectingCapabilities.IdentityResolveProvider['lastRecognized'],
ref: Next.CollectingCapabilities.IdentityResolveProvider['recognized'],
cancel: AbortSignal,
) {
const selfSelector = selfInfoSelectors().handle
Expand All @@ -32,10 +34,52 @@ function resolveLastRecognizedIdentityInner(
cancel.addEventListener('abort', () => watcher.stopWatch())
}

function resolveCurrentVisitingIdentityInner(
ref: Next.CollectingCapabilities.IdentityResolveProvider['recognized'],
cancel: AbortSignal,
) {
const headerPhotoSelector = searchProfileTabListSelector()
const assign = async () => {
await delay(500)
const bio = getBioDescription()
const nickname = getNickname()
const handle = getTwitterId()
const avatar = getAvatar()
ref.value = {
identifier: new ProfileIdentifier(twitterBase.networkIdentifier, handle),
nickname,
avatar,
bio,
}
}

const watcher = new MutationObserverWatcher(headerPhotoSelector)
.addListener('onAdd', () => assign())
.addListener('onChange', () => assign())
.startWatch({
childList: true,
subtree: true,
})

window.addEventListener('locationchange', assign)
cancel.addEventListener('abort', () => {
window.removeEventListener('locationchange', assign)
watcher.stopWatch()
})
}

export const IdentityProviderTwitter: Next.CollectingCapabilities.IdentityResolveProvider = {
hasDeprecatedPlaceholderName: false,
lastRecognized: creator.IdentityResolveProviderLastRecognized(),
recognized: creator.EmptyIdentityResolveProviderState(),
start(cancel) {
resolveLastRecognizedIdentityInner(this.recognized, cancel)
},
}

export const CurrentVisitingIdentityProviderTwitter: Next.CollectingCapabilities.IdentityResolveProvider = {
hasDeprecatedPlaceholderName: false,
recognized: creator.EmptyIdentityResolveProviderState(),
start(cancel) {
resolveLastRecognizedIdentityInner(this.lastRecognized, cancel)
resolveCurrentVisitingIdentityInner(this.recognized, cancel)
},
}
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ function registerPostCollectorInner(
}

export const PostProviderTwitter: Next.CollectingCapabilities.PostsProvider = {
posts: creator.PostProviderStore(),
posts: creator.EmptyPostProviderState(),
start(cancel) {
registerPostCollectorInner(this.posts, cancel)
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ const useStyles = makeStyles<StyleProps>()((theme, props) => ({
color: props.color,
font: props.font,
fontSize: props.fontSize,
fontWeight: 700,
fontWeight: 500,
'&:hover': {
color: props.color,
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { openComposeBoxTwitter } from './automation/openComposeBox'
import { pasteTextToCompositionTwitter } from './automation/pasteTextToComposition'
import { gotoNewsFeedPageTwitter } from './automation/gotoNewsFeedPage'
import { gotoProfilePageTwitter } from './automation/gotoProfilePage'
import { IdentityProviderTwitter } from './collecting/identity'
import { IdentityProviderTwitter, CurrentVisitingIdentityProviderTwitter } from './collecting/identity'
import { PostProviderTwitter } from './collecting/post'
import { PaletteModeProviderTwitter, useThemeTwitterVariant } from './customization/custom'
import { injectToolboxHintAtTwitter } from './injection/ToolboxHint'
Expand Down Expand Up @@ -118,6 +118,7 @@ const twitterUI: SocialNetworkUI.Definition = {
},
collecting: {
identityProvider: IdentityProviderTwitter,
currentVisitingIdentityProvider: CurrentVisitingIdentityProviderTwitter,
postsProvider: PostProviderTwitter,
getSearchedKeyword: getSearchedKeywordAtTwitter,
},
Expand Down Expand Up @@ -168,7 +169,7 @@ const twitterUI: SocialNetworkUI.Definition = {
// ! Change this might be a breaking change !
return new ProfileIdentifier(
'twitter.com',
ProfileIdentifier.getUserName(IdentityProviderTwitter.lastRecognized.value.identifier) ||
ProfileIdentifier.getUserName(IdentityProviderTwitter.recognized.value.identifier) ||
ProfileIdentifier.getUserName(currentSelectedIdentity[twitterBase.networkIdentifier].value) ||
ProfileIdentifier.getUserName(globalUIState.profiles.value[0].identifier) ||
unreachable('Cannot figure out password' as never),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ export const searchNewTweetButtonSelector: () => LiveSelector<E, true> = () =>
querySelector<E>('[data-testid="SideNav_NewTweet_Button"]')
export const searchNickNameSelector: () => LiveSelector<E, true> = () =>
querySelector<E>('[data-testid="UserProfileHeader_Items"]')
export const searchAvatarSelector: () => LiveSelector<E, true> = () =>
querySelector<E>('[data-testid="primaryColumn"] a[role="link"][href$="/photo"] img')
export const searchHeaderPhotoSelector: () => LiveSelector<E, true> = () =>
querySelector<E>('[data-testid="primaryColumn"] a[role="link"][href$=/header_photo] img')
export const bioCardSelector = <SingleMode extends boolean = true>(singleMode = true) =>
querySelector<HTMLDivElement, SingleMode>(
[
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { isNull } from 'lodash-es'
import type { SocialNetwork } from '../../../social-network'
import { bioDescriptionSelector, searchNickNameSelector } from './selector'
import { bioDescriptionSelector, searchAvatarSelector, searchNickNameSelector } from './selector'

/**
* @link https://help.twitter.com/en/managing-your-account/twitter-username-rules
Expand Down Expand Up @@ -40,3 +40,11 @@ export const getBioDescription = () => {
const node = bioDescriptionSelector().evaluate()
return node?.innerText ?? ''
}

export const getAvatar = () => {
const node = searchAvatarSelector().evaluate() as HTMLImageElement
if (!node) return ''

const imageURL = node.getAttribute('src') ?? ''
return imageURL.trim()
}
Loading