From 44a9b6ee0e5bb1861145e492b2726bb2097dfdb0 Mon Sep 17 00:00:00 2001 From: codytseng Date: Wed, 21 May 2025 22:52:43 +0800 Subject: [PATCH] feat: force refresh of user relay list cache when viewing profile --- src/hooks/useSearchProfiles.tsx | 2 +- src/pages/secondary/ProfileListPage/index.tsx | 2 +- src/pages/secondary/ProfilePage/index.tsx | 15 +++- src/services/client.service.ts | 78 ++++++++++--------- 4 files changed, 57 insertions(+), 40 deletions(-) diff --git a/src/hooks/useSearchProfiles.tsx b/src/hooks/useSearchProfiles.tsx index c2b518e..16c1a06 100644 --- a/src/hooks/useSearchProfiles.tsx +++ b/src/hooks/useSearchProfiles.tsx @@ -22,7 +22,7 @@ export function useSearchProfiles(search: string, limit: number) { setIsFetching(true) setProfiles([]) try { - const profiles = await client.fetchProfiles( + const profiles = await client.searchProfiles( searchableRelayUrls.concat(SEARCHABLE_RELAY_URLS).slice(0, 4), { search, diff --git a/src/pages/secondary/ProfileListPage/index.tsx b/src/pages/secondary/ProfileListPage/index.tsx index dc35108..ab75ed8 100644 --- a/src/pages/secondary/ProfileListPage/index.tsx +++ b/src/pages/secondary/ProfileListPage/index.tsx @@ -66,7 +66,7 @@ const ProfileListPage = forwardRef(({ index }: { index?: number }, ref) => { if (urls.length === 0) { return setHasMore(false) } - const profiles = await client.fetchProfiles(urls, { ...filter, limit: LIMIT }) + const profiles = await client.searchProfiles(urls, { ...filter, limit: LIMIT }) const newPubkeySet = new Set() profiles.forEach((profile) => { if (!pubkeySet.has(profile.pubkey)) { diff --git a/src/pages/secondary/ProfilePage/index.tsx b/src/pages/secondary/ProfilePage/index.tsx index 41cc772..18079bd 100644 --- a/src/pages/secondary/ProfilePage/index.tsx +++ b/src/pages/secondary/ProfilePage/index.tsx @@ -18,6 +18,7 @@ import { generateImageByPubkey } from '@/lib/pubkey' import { SecondaryPageLink, useSecondaryPage } from '@/PageManager' import { useMuteList } from '@/providers/MuteListProvider' import { useNostr } from '@/providers/NostrProvider' +import client from '@/services/client.service' import { Link, Zap } from 'lucide-react' import { forwardRef, useCallback, useEffect, useMemo, useState } from 'react' import { useTranslation } from 'react-i18next' @@ -28,7 +29,7 @@ import Relays from './Relays' const ProfilePage = forwardRef(({ id, index }: { id?: string; index?: number }, ref) => { const { t } = useTranslation() const { push } = useSecondaryPage() - const { profile, isFetching } = useFetchProfile(id, true) + const { profile, isFetching } = useFetchProfile(id) const { pubkey: accountPubkey } = useNostr() const { mutePubkeys } = useMuteList() const { followings } = useFetchFollowings(profile?.pubkey) @@ -50,6 +51,18 @@ const ProfilePage = forwardRef(({ id, index }: { id?: string; index?: number }, } }, []) + useEffect(() => { + if (!profile?.pubkey) return + + const forceUpdateCache = async () => { + await Promise.all([ + client.forceUpdateRelayListEvent(profile.pubkey), + client.fetchProfile(profile.pubkey, true) + ]) + } + forceUpdateCache() + }, [profile?.pubkey]) + useEffect(() => { if (!topContainer) return diff --git a/src/services/client.service.ts b/src/services/client.service.ts index 8f058e2..0ad9a3c 100644 --- a/src/services/client.service.ts +++ b/src/services/client.service.ts @@ -699,7 +699,7 @@ class ClientService extends EventTarget { } } - async fetchProfiles(relayUrls: string[], filter: Filter): Promise { + async searchProfiles(relayUrls: string[], filter: Filter): Promise { const events = await this.query(relayUrls, { ...filter, kinds: [kinds.Metadata] @@ -715,21 +715,32 @@ class ClientService extends EventTarget { } async fetchRelayList(pubkey: string): Promise { - const event = await this.relayListEventDataLoader.load(pubkey) - if (!event) { - return { - write: BIG_RELAY_URLS, - read: BIG_RELAY_URLS, - originalRelays: [] - } - } - return getRelayListFromRelayListEvent(event) + const [relayList] = await this.fetchRelayLists([pubkey]) + return relayList } - async fetchRelayLists(pubkeys: string[]) { - const events = await this.relayListEventDataLoader.loadMany(pubkeys) - return events.map((event) => { + async fetchRelayLists(pubkeys: string[]): Promise { + const relayEvents = await indexedDb.getManyReplaceableEvents(pubkeys, kinds.RelayList) + const nonExistingPubkeyIndexMap = new Map() + pubkeys.forEach((pubkey, i) => { + if (!relayEvents[i]) { + nonExistingPubkeyIndexMap.set(pubkey, i) + } + }) + const newEvents = await this.relayListEventDataLoader.loadMany( + Array.from(nonExistingPubkeyIndexMap.keys()) + ) + newEvents.forEach((event) => { if (event && !(event instanceof Error)) { + const index = nonExistingPubkeyIndexMap.get(event.pubkey) + if (index !== undefined) { + relayEvents[index] = event + } + } + }) + + return relayEvents.map((event) => { + if (event) { return getRelayListFromRelayListEvent(event) } return { @@ -740,6 +751,10 @@ class ClientService extends EventTarget { }) } + async forceUpdateRelayListEvent(pubkey: string) { + await this.relayListEventBatchLoadFn([pubkey]) + } + async fetchFollowListEvent(pubkey: string, storeToIndexedDb = false) { const event = await this.followListCache.fetch(pubkey) if (storeToIndexedDb && event) { @@ -998,33 +1013,22 @@ class ClientService extends EventTarget { } private async relayListEventBatchLoadFn(pubkeys: readonly string[]) { - const relayEvents = await indexedDb.getManyReplaceableEvents(pubkeys, kinds.RelayList) - const nonExistingPubkeys = pubkeys.filter((_, i) => !relayEvents[i]) - if (nonExistingPubkeys.length) { - const events = await this.query(BIG_RELAY_URLS, { - authors: nonExistingPubkeys as string[], - kinds: [kinds.RelayList], - limit: pubkeys.length - }) - const eventsMap = new Map() - for (const event of events) { - const pubkey = event.pubkey - const existing = eventsMap.get(pubkey) - if (!existing || existing.created_at < event.created_at) { - eventsMap.set(pubkey, event) - } + const events = await this.query(BIG_RELAY_URLS, { + authors: pubkeys as string[], + kinds: [kinds.RelayList], + limit: pubkeys.length + }) + const eventsMap = new Map() + for (const event of events) { + const pubkey = event.pubkey + const existing = eventsMap.get(pubkey) + if (!existing || existing.created_at < event.created_at) { + eventsMap.set(pubkey, event) } - Array.from(eventsMap.values()).forEach((evt) => indexedDb.putReplaceableEvent(evt)) - nonExistingPubkeys.forEach((pubkey) => { - const event = eventsMap.get(pubkey) - if (event) { - const index = pubkeys.indexOf(pubkey) - relayEvents[index] = event - } - }) } + Array.from(eventsMap.values()).forEach((evt) => indexedDb.putReplaceableEvent(evt)) - return relayEvents + return pubkeys.map((pubkey) => eventsMap.get(pubkey)) } private async _fetchFollowListEvent(pubkey: string) {