An ATproto social media client -- with an independent Appview.

Merge pull request #2679 from bluesky-social/hailey/check-blocks-load-profile

clear cache when blocking/unblocking and whenever we get blocked, better invalidation logic for `useProfileQuery`

authored by

Hailey and committed by
GitHub
40581746 c59741c1

+48 -13
+13
src/state/queries/post-feed.ts
··· 28 28 import {KnownError} from '#/view/com/posts/FeedErrorMessage' 29 29 import {embedViewRecordToPostView, getEmbeddedPost} from './util' 30 30 import {useModerationOpts} from './preferences' 31 + import {queryClient} from 'lib/react-query' 31 32 32 33 type ActorDid = string 33 34 type AuthorFilter = ··· 444 445 throw new Error(KnownError.FeedNSFPublic) 445 446 } 446 447 } 448 + 449 + export function resetProfilePostsQueries(did: string, timeout = 0) { 450 + setTimeout(() => { 451 + queryClient.resetQueries({ 452 + predicate: query => 453 + !!( 454 + query.queryKey[0] === 'post-feed' && 455 + (query.queryKey[1] as string)?.includes(did) 456 + ), 457 + }) 458 + }, timeout) 459 + }
+14 -6
src/state/queries/profile.ts
··· 17 17 import {uploadBlob} from '#/lib/api' 18 18 import {until} from '#/lib/async/until' 19 19 import {Shadow} from '#/state/cache/types' 20 + import {resetProfilePostsQueries} from '#/state/queries/post-feed' 20 21 import {useToggleMutationQueue} from '#/lib/hooks/useToggleMutationQueue' 21 22 import {RQKEY as RQKEY_MY_MUTED} from './my-muted-accounts' 22 23 import {RQKEY as RQKEY_MY_BLOCKED} from './my-blocked-accounts' ··· 26 27 export const RQKEY = (did: string) => ['profile', did] 27 28 export const profilesQueryKey = (handles: string[]) => ['profiles', handles] 28 29 29 - export function useProfileQuery({did}: {did: string | undefined}) { 30 - const {currentAccount} = useSession() 31 - const isCurrentAccount = did === currentAccount?.did 32 - 30 + export function useProfileQuery({ 31 + did, 32 + staleTime = STALE.SECONDS.FIFTEEN, 33 + }: { 34 + did: string | undefined 35 + staleTime?: number 36 + }) { 33 37 return useQuery({ 34 38 // WARNING 35 39 // this staleTime is load-bearing 36 40 // if you remove it, the UI infinite-loops 37 41 // -prf 38 - staleTime: isCurrentAccount ? STALE.SECONDS.THIRTY : STALE.MINUTES.FIVE, 42 + staleTime, 39 43 refetchOnWindowFocus: true, 40 44 queryKey: RQKEY(did || ''), 41 45 queryFn: async () => { ··· 375 379 {subject: did, createdAt: new Date().toISOString()}, 376 380 ) 377 381 }, 378 - onSuccess() { 382 + onSuccess(_, {did}) { 379 383 queryClient.invalidateQueries({queryKey: RQKEY_MY_BLOCKED()}) 384 + resetProfilePostsQueries(did, 1000) 380 385 }, 381 386 }) 382 387 } ··· 393 398 repo: currentAccount.did, 394 399 rkey, 395 400 }) 401 + }, 402 + onSuccess(_, {did}) { 403 + resetProfilePostsQueries(did, 1000) 396 404 }, 397 405 }) 398 406 }
+2 -2
src/view/com/modals/ProfilePreview.tsx
··· 27 27 data: profile, 28 28 error: profileError, 29 29 refetch: refetchProfile, 30 - isFetching: isFetchingProfile, 30 + isLoading: isLoadingProfile, 31 31 } = useProfileQuery({ 32 32 did: did, 33 33 }) 34 34 35 - if (isFetchingProfile || !moderationOpts) { 35 + if (isLoadingProfile || !moderationOpts) { 36 36 return ( 37 37 <CenteredView style={[pal.view, s.flex1]}> 38 38 <ProfileHeader
+5 -1
src/view/com/util/UserInfoText.tsx
··· 9 9 import {sanitizeHandle} from 'lib/strings/handles' 10 10 import {makeProfileLink} from 'lib/routes/links' 11 11 import {useProfileQuery} from '#/state/queries/profile' 12 + import {STALE} from '#/state/queries' 12 13 13 14 export function UserInfoText({ 14 15 type = 'md', ··· 29 30 attr = attr || 'handle' 30 31 failed = failed || 'user' 31 32 32 - const {data: profile, isError} = useProfileQuery({did}) 33 + const {data: profile, isError} = useProfileQuery({ 34 + did, 35 + staleTime: STALE.INFINITY, 36 + }) 33 37 34 38 let inner 35 39 if (isError) {
+14 -4
src/view/screens/Profile.tsx
··· 21 21 import {ComposeIcon2} from 'lib/icons' 22 22 import {useSetTitle} from 'lib/hooks/useSetTitle' 23 23 import {combinedDisplayName} from 'lib/strings/display-names' 24 - import {FeedDescriptor} from '#/state/queries/post-feed' 24 + import { 25 + FeedDescriptor, 26 + resetProfilePostsQueries, 27 + } from '#/state/queries/post-feed' 25 28 import {useResolveDidQuery} from '#/state/queries/resolve-uri' 26 29 import {useProfileQuery} from '#/state/queries/profile' 27 30 import {useProfileShadow} from '#/state/cache/profile-shadow' ··· 55 58 data: resolvedDid, 56 59 error: resolveError, 57 60 refetch: refetchDid, 58 - isInitialLoading: isInitialLoadingDid, 61 + isLoading: isLoadingDid, 59 62 } = useResolveDidQuery(name) 60 63 const { 61 64 data: profile, 62 65 error: profileError, 63 66 refetch: refetchProfile, 64 - isInitialLoading: isInitialLoadingProfile, 67 + isLoading: isLoadingProfile, 65 68 } = useProfileQuery({ 66 69 did: resolvedDid, 67 70 }) ··· 74 77 } 75 78 }, [resolveError, refetchDid, refetchProfile]) 76 79 77 - if (isInitialLoadingDid || isInitialLoadingProfile || !moderationOpts) { 80 + // When we open the profile, we want to reset the posts query if we are blocked. 81 + React.useEffect(() => { 82 + if (resolvedDid && profile?.viewer?.blockedBy) { 83 + resetProfilePostsQueries(resolvedDid) 84 + } 85 + }, [profile?.viewer?.blockedBy, resolvedDid]) 86 + 87 + if (isLoadingDid || isLoadingProfile || !moderationOpts) { 78 88 return ( 79 89 <CenteredView> 80 90 <ProfileHeader