Clarify intent behind precacheProfile and its unstable query cache
This commit is contained in:
@@ -44,9 +44,13 @@ export const profilesQueryKey = (handles: string[]) => [
|
|||||||
handles,
|
handles,
|
||||||
]
|
]
|
||||||
|
|
||||||
const profileBasicQueryKeyRoot = 'profileBasic'
|
const unstableProfileViewCacheQueryKeyRoot = 'unstableProfileViewCache'
|
||||||
export const profileBasicQueryKey = (didOrHandle: string) => [
|
/**
|
||||||
profileBasicQueryKeyRoot,
|
* 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,
|
didOrHandle,
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -74,9 +78,10 @@ export function useProfileQuery({
|
|||||||
placeholderData: () => {
|
placeholderData: () => {
|
||||||
if (!did) return
|
if (!did) return
|
||||||
|
|
||||||
return queryClient.getQueryData<AppBskyActorDefs.ProfileViewDetailed>(
|
// This can return any profile view type
|
||||||
profileBasicQueryKey(did),
|
return queryClient.getQueryData<atp.profile.AnyProfileView>(
|
||||||
)
|
unstableProfileViewCacheQueryKey(did),
|
||||||
|
) as AppBskyActorDefs.ProfileViewDetailed
|
||||||
},
|
},
|
||||||
enabled: !!did,
|
enabled: !!did,
|
||||||
})
|
})
|
||||||
@@ -507,12 +512,23 @@ 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(
|
export function precacheProfile(
|
||||||
queryClient: QueryClient,
|
queryClient: QueryClient,
|
||||||
profile: AppBskyActorDefs.ProfileViewBasic,
|
profile: atp.profile.AnyProfileView,
|
||||||
) {
|
) {
|
||||||
queryClient.setQueryData(profileBasicQueryKey(profile.handle), profile)
|
queryClient.setQueryData(
|
||||||
queryClient.setQueryData(profileBasicQueryKey(profile.did), profile)
|
unstableProfileViewCacheQueryKey(profile.handle),
|
||||||
|
profile,
|
||||||
|
)
|
||||||
|
queryClient.setQueryData(
|
||||||
|
unstableProfileViewCacheQueryKey(profile.did),
|
||||||
|
profile,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function whenAppViewReady(
|
async function whenAppViewReady(
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import {AppBskyActorDefs, AtUri} from '@atproto/api'
|
import {AtUri} from '@atproto/api'
|
||||||
import {
|
import {
|
||||||
QueryClient,
|
QueryClient,
|
||||||
useQuery,
|
useQuery,
|
||||||
@@ -8,7 +8,8 @@ import {
|
|||||||
|
|
||||||
import {STALE} from '#/state/queries'
|
import {STALE} from '#/state/queries'
|
||||||
import {useAgent} from '#/state/session'
|
import {useAgent} from '#/state/session'
|
||||||
import {profileBasicQueryKey as RQKEY_PROFILE_BASIC} from './profile'
|
import * as atp from '#/types/atproto'
|
||||||
|
import {unstableProfileViewCacheQueryKey} from './profile'
|
||||||
|
|
||||||
const RQKEY_ROOT = 'resolved-did'
|
const RQKEY_ROOT = 'resolved-did'
|
||||||
export const RQKEY = (didOrHandle: string) => [RQKEY_ROOT, didOrHandle]
|
export const RQKEY = (didOrHandle: string) => [RQKEY_ROOT, didOrHandle]
|
||||||
@@ -46,10 +47,10 @@ export function useResolveDidQuery(didOrHandle: string | undefined) {
|
|||||||
// Return undefined if no did or handle
|
// Return undefined if no did or handle
|
||||||
if (!didOrHandle) return
|
if (!didOrHandle) return
|
||||||
|
|
||||||
const profile =
|
// This can return any profile view type
|
||||||
queryClient.getQueryData<AppBskyActorDefs.ProfileViewBasic>(
|
const profile = queryClient.getQueryData<atp.profile.AnyProfileView>(
|
||||||
RQKEY_PROFILE_BASIC(didOrHandle),
|
unstableProfileViewCacheQueryKey(didOrHandle),
|
||||||
)
|
)
|
||||||
return profile?.did
|
return profile?.did
|
||||||
},
|
},
|
||||||
enabled: !!didOrHandle,
|
enabled: !!didOrHandle,
|
||||||
|
|||||||
@@ -26,44 +26,3 @@ export type AnyProfileView =
|
|||||||
| AppBskyActorDefs.ProfileView
|
| AppBskyActorDefs.ProfileView
|
||||||
| AppBskyActorDefs.ProfileViewDetailed
|
| AppBskyActorDefs.ProfileViewDetailed
|
||||||
| ChatBskyActorDefs.ProfileViewBasic
|
| ChatBskyActorDefs.ProfileViewBasic
|
||||||
|
|
||||||
/**
|
|
||||||
* Maps any profile view type to `ProfileViewBasic`.
|
|
||||||
*/
|
|
||||||
export function anyToBasic(
|
|
||||||
view: AnyProfileView,
|
|
||||||
): AppBskyActorDefs.ProfileViewBasic {
|
|
||||||
return {
|
|
||||||
$type: 'app.bsky.actor.defs#profileViewBasic',
|
|
||||||
did: view.did,
|
|
||||||
handle: view.handle,
|
|
||||||
displayName: view.displayName,
|
|
||||||
avatar: view.avatar,
|
|
||||||
associated: view.associated,
|
|
||||||
viewer: view.viewer,
|
|
||||||
labels: view.labels,
|
|
||||||
// `createdAt` doesn't exist in ChatBskyActorDefs.ProfileViewBasic
|
|
||||||
createdAt: 'createdAt' in view ? view.createdAt : undefined,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Maps `ProfileViewDetailed` to `ProfileView`.
|
|
||||||
*/
|
|
||||||
export function detailedToView(
|
|
||||||
view: AppBskyActorDefs.ProfileViewDetailed,
|
|
||||||
): AppBskyActorDefs.ProfileView {
|
|
||||||
return {
|
|
||||||
$type: 'app.bsky.actor.defs#profileView',
|
|
||||||
did: view.did,
|
|
||||||
handle: view.handle,
|
|
||||||
displayName: view.displayName,
|
|
||||||
avatar: view.avatar,
|
|
||||||
associated: view.associated,
|
|
||||||
viewer: view.viewer,
|
|
||||||
labels: view.labels,
|
|
||||||
createdAt: view.createdAt,
|
|
||||||
description: view.description,
|
|
||||||
indexedAt: view.indexedAt,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -121,14 +121,7 @@ let NotificationFeedItem = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const onBeforePress = React.useCallback(() => {
|
const onBeforePress = React.useCallback(() => {
|
||||||
/*
|
precacheProfile(queryClient, item.notification.author)
|
||||||
* Notification returns ProfileView, which has one additional field on top
|
|
||||||
* of `Basic`: `indexedAt`. Harmless for now, but should be fixed.
|
|
||||||
*/
|
|
||||||
precacheProfile(
|
|
||||||
queryClient,
|
|
||||||
atp.profile.anyToBasic(item.notification.author),
|
|
||||||
)
|
|
||||||
}, [queryClient, item.notification.author])
|
}, [queryClient, item.notification.author])
|
||||||
|
|
||||||
const authors: Author[] = useMemo(() => {
|
const authors: Author[] = useMemo(() => {
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ export function ProfileCard({
|
|||||||
|
|
||||||
const onBeforePress = React.useCallback(() => {
|
const onBeforePress = React.useCallback(() => {
|
||||||
onPress?.()
|
onPress?.()
|
||||||
precacheProfile(queryClient, atp.profile.anyToBasic(profile))
|
precacheProfile(queryClient, profile)
|
||||||
}, [onPress, profile, queryClient])
|
}, [onPress, profile, queryClient])
|
||||||
|
|
||||||
if (!moderationOpts) {
|
if (!moderationOpts) {
|
||||||
|
|||||||
@@ -427,7 +427,7 @@ let PreviewableUserAvatar = ({
|
|||||||
|
|
||||||
const onPress = React.useCallback(() => {
|
const onPress = React.useCallback(() => {
|
||||||
onBeforePress?.()
|
onBeforePress?.()
|
||||||
precacheProfile(queryClient, atp.profile.anyToBasic(profile))
|
precacheProfile(queryClient, profile)
|
||||||
}, [profile, queryClient, onBeforePress])
|
}, [profile, queryClient, onBeforePress])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
Reference in New Issue
Block a user