diff --git a/src/state/queries/profile.ts b/src/state/queries/profile.ts index a5edd9b405..5ac50fba55 100644 --- a/src/state/queries/profile.ts +++ b/src/state/queries/profile.ts @@ -23,6 +23,10 @@ import {logEvent, LogEvents, toClout} from '#/lib/statsig/statsig' import {Shadow} from '#/state/cache/types' import {STALE} from '#/state/queries' import {resetProfilePostsQueries} from '#/state/queries/post-feed' +import { + unstableCacheProfileView, + useUnstableProfileViewCache, +} from '#/state/queries/unstable-profile-cache' import * as userActionHistory from '#/state/userActionHistory' import * as atp from '#/types/atproto' import {updateProfileShadow} from '../cache/profile-shadow' @@ -35,6 +39,12 @@ import {RQKEY as RQKEY_LIST_CONVOS} from './messages/list-conversations' import {RQKEY as RQKEY_MY_BLOCKED} from './my-blocked-accounts' import {RQKEY as RQKEY_MY_MUTED} from './my-muted-accounts' +export * from '#/state/queries/unstable-profile-cache' +/** + * @deprecated use {@link unstableCacheProfileView} instead + */ +export const precacheProfile = unstableCacheProfileView + const RQKEY_ROOT = 'profile' export const RQKEY = (did: string) => [RQKEY_ROOT, did] @@ -44,16 +54,6 @@ export const profilesQueryKey = (handles: string[]) => [ handles, ] -const unstableProfileViewCacheQueryKeyRoot = 'unstableProfileViewCache' -/** - * We cache multiple profile view types by this query key. If object shapes are - * important, you should validate the type when accessing the data. - */ -export const unstableProfileViewCacheQueryKey = (didOrHandle: string) => [ - unstableProfileViewCacheQueryKeyRoot, - didOrHandle, -] - export function useProfileQuery({ did, staleTime = STALE.SECONDS.FIFTEEN, @@ -61,8 +61,8 @@ export function useProfileQuery({ did: string | undefined staleTime?: number }) { - const queryClient = useQueryClient() const agent = useAgent() + const {getUnstableProfile} = useUnstableProfileViewCache() return useQuery({ // WARNING // this staleTime is load-bearing @@ -77,11 +77,7 @@ export function useProfileQuery({ }, placeholderData: () => { if (!did) return - - // This can return any profile view type - return queryClient.getQueryData( - unstableProfileViewCacheQueryKey(did), - ) as AppBskyActorDefs.ProfileViewDetailed + return getUnstableProfile(did) as AppBskyActorDefs.ProfileViewDetailed }, enabled: !!did, }) @@ -512,25 +508,6 @@ function useProfileUnblockMutation() { }) } -/** - * This function is used to precache a profile view in the query client. Any - * profile view type is accepted, so you should validate the type when - * accessing the data. - */ -export function precacheProfile( - queryClient: QueryClient, - profile: atp.profile.AnyProfileView, -) { - queryClient.setQueryData( - unstableProfileViewCacheQueryKey(profile.handle), - profile, - ) - queryClient.setQueryData( - unstableProfileViewCacheQueryKey(profile.did), - profile, - ) -} - async function whenAppViewReady( agent: BskyAgent, actor: string, diff --git a/src/state/queries/resolve-uri.ts b/src/state/queries/resolve-uri.ts index 8efa630599..1422a2daef 100644 --- a/src/state/queries/resolve-uri.ts +++ b/src/state/queries/resolve-uri.ts @@ -1,15 +1,9 @@ import {AtUri} from '@atproto/api' -import { - QueryClient, - useQuery, - useQueryClient, - UseQueryResult, -} from '@tanstack/react-query' +import {QueryClient, useQuery, UseQueryResult} from '@tanstack/react-query' import {STALE} from '#/state/queries' import {useAgent} from '#/state/session' -import * as atp from '#/types/atproto' -import {unstableProfileViewCacheQueryKey} from './profile' +import {useUnstableProfileViewCache} from './profile' const RQKEY_ROOT = 'resolved-did' export const RQKEY = (didOrHandle: string) => [RQKEY_ROOT, didOrHandle] @@ -29,8 +23,8 @@ export function useResolveUriQuery(uri: string | undefined): UriUseQueryResult { } export function useResolveDidQuery(didOrHandle: string | undefined) { - const queryClient = useQueryClient() const agent = useAgent() + const {getUnstableProfile} = useUnstableProfileViewCache() return useQuery({ staleTime: STALE.HOURS.ONE, @@ -46,11 +40,7 @@ export function useResolveDidQuery(didOrHandle: string | undefined) { initialData: () => { // Return undefined if no did or handle if (!didOrHandle) return - - // This can return any profile view type - const profile = queryClient.getQueryData( - unstableProfileViewCacheQueryKey(didOrHandle), - ) + const profile = getUnstableProfile(didOrHandle) return profile?.did }, enabled: !!didOrHandle, diff --git a/src/state/queries/unstable-profile-cache.ts b/src/state/queries/unstable-profile-cache.ts new file mode 100644 index 0000000000..40eae6dcda --- /dev/null +++ b/src/state/queries/unstable-profile-cache.ts @@ -0,0 +1,51 @@ +import {useCallback} from 'react' +import {QueryClient,useQueryClient} from '@tanstack/react-query' + +import * as atp from '#/types/atproto' + +const unstableProfileViewCacheQueryKeyRoot = 'unstableProfileViewCache' +export const unstableProfileViewCacheQueryKey = (didOrHandle: string) => [ + unstableProfileViewCacheQueryKeyRoot, + didOrHandle, +] + +/** + * Used as a rough cache of profile views to make loading snappier. This method + * accepts and stores any profile view type by both handle and DID. + * + * Access the cache via {@link useUnstableProfileViewCache}. + */ +export function unstableCacheProfileView( + queryClient: QueryClient, + profile: atp.profile.AnyProfileView, +) { + queryClient.setQueryData( + unstableProfileViewCacheQueryKey(profile.handle), + profile, + ) + queryClient.setQueryData( + unstableProfileViewCacheQueryKey(profile.did), + profile, + ) +} + +/** + * Hook to access the unstable profile view cache. This cache can return ANY + * profile view type, so if the object shape is important, you need to use the + * identity validators shipped in the atproto SDK e.g. + * `AppBskyActorDefs.isValidProfileViewBasic` to confirm before using. + * + * To cache a profile, use {@link unstableCacheProfileView}. + */ +export function useUnstableProfileViewCache() { + const qc = useQueryClient() + const getUnstableProfile = useCallback( + (didOrHandle: string) => { + return qc.getQueryData( + unstableProfileViewCacheQueryKey(didOrHandle), + ) + }, + [qc], + ) + return {getUnstableProfile} +}